Last active
September 23, 2015 07:45
-
-
Save lukego/d801cc7ad5fa68d884fb to your computer and use it in GitHub Desktop.
LuaJIT profiler extension to count loops of traces separately [draft]
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/lib/luajit/src/jit/p.lua b/lib/luajit/src/jit/p.lua | |
index d894bb7..b619517 100644 | |
--- a/lib/luajit/src/jit/p.lua | |
+++ b/lib/luajit/src/jit/p.lua | |
@@ -71,7 +71,8 @@ local map_vmmode = { | |
} | |
-- Profiler callback. | |
-local function prof_cb(th, samples, vmmode) | |
+local function prof_cb(th, samples, vmmode, ip) | |
+ print("samples", samples, "vmmode", vmmode, "ip", bit.tohex(ip)) | |
prof_samples = prof_samples + samples | |
local key_stack, key_stack2, key_state | |
-- Collect keys for sample. | |
@@ -106,7 +107,9 @@ local function prof_cb(th, samples, vmmode) | |
local fi = jutil.funcinfo(extra.func, extra.pc) | |
if fi.loc then loc = fi.loc end | |
end | |
- local s = ("TRACE %3d %-8s %-10s%s %s"):format(vmmode, parent, lnk, z, loc) | |
+ print("ip", bit.tohex(ip), "szmcode", info.szmcode, "mcode", bit.tohex(info.mcode), "mcloop", info.mcloop) | |
+ local loop = (ip >= info.mcode+info.mcloop) and ':LOOP' or ' ' | |
+ local s = ("TRACE %3d%s %-8s %-10s%s %s"):format(vmmode, loop, parent, lnk, z, loc) | |
key_state = map_vmmode[vmmode] or s | |
end | |
else | |
diff --git a/lib/luajit/src/lib_jit.c b/lib/luajit/src/lib_jit.c | |
index 9e0e01d..9f7c041 100644 | |
--- a/lib/luajit/src/lib_jit.c | |
+++ b/lib/luajit/src/lib_jit.c | |
@@ -293,14 +293,23 @@ LJLIB_CF(jit_util_traceinfo) | |
GCtrace *T = jit_checktrace(L); | |
if (T) { | |
GCtab *t; | |
+ //int gc = 0; | |
+ int i; | |
lua_createtable(L, 0, 8); /* Increment hash size if fields are added. */ | |
t = tabV(L->top-1); | |
setintfield(L, t, "nins", (int32_t)T->nins - REF_BIAS - 1); | |
setintfield(L, t, "nk", REF_BIAS - (int32_t)T->nk); | |
setintfield(L, t, "link", T->link); | |
setintfield(L, t, "nexit", T->nsnap); | |
+ setintfield(L, t, "szmcode", T->szmcode); | |
+ setintfield(L, t, "mcode", T->mcode); | |
+ setintfield(L, t, "mcloop", T->mcloop); | |
setstrV(L, L->top++, lj_str_newz(L, jit_trlinkname[T->linktype])); | |
lua_setfield(L, -2, "linktype"); | |
+ | |
+ for (i = 0; i > T->nins-1; i++) { | |
+ if ((IROp)T->ir[i].o == IR_GCSTEP) { printf("GC\n"); } | |
+ } | |
/* There are many more fields. Add them only when needed. */ | |
return 1; | |
} | |
@@ -543,7 +552,7 @@ static const char KEY_PROFILE_THREAD = 't'; | |
static const char KEY_PROFILE_FUNC = 'f'; | |
static void jit_profile_callback(lua_State *L2, lua_State *L, int samples, | |
- int vmstate) | |
+ int vmstate, uint64_t ip) | |
{ | |
TValue key; | |
cTValue *tv; | |
@@ -559,7 +568,8 @@ static void jit_profile_callback(lua_State *L2, lua_State *L, int samples, | |
setintV(L2->top++, vmstate-256); | |
else | |
setstrV(L2, L2->top++, lj_str_new(L2, &vmst, 1)); | |
- status = lua_pcall(L2, 3, 0, 0); /* callback(thread, samples, vmstate) */ | |
+ setintV(L2->top++, ip); | |
+ status = lua_pcall(L2, 4, 0, 0); /* callback(thread, samples, vmstate) */ | |
if (status) { | |
if (G(L2)->panic) G(L2)->panic(L2); | |
exit(EXIT_FAILURE); | |
diff --git a/lib/luajit/src/lj_profile.c b/lib/luajit/src/lj_profile.c | |
index f4d6fe1..d8c14fb 100644 | |
--- a/lib/luajit/src/lj_profile.c | |
+++ b/lib/luajit/src/lj_profile.c | |
@@ -38,6 +38,7 @@ | |
#include <sys/ioctl.h> | |
#include <linux/perf_event.h> | |
#include <sys/prctl.h> | |
+#include <ucontext.h> | |
#endif | |
@@ -77,6 +78,7 @@ typedef struct ProfileState { | |
char *flavour; /* What generates profiling events. */ | |
int perf_event_fd; /* Performace event file descriptor */ | |
int vmstate; /* VM state when profile timer triggered. */ | |
+ uint64_t ip; /* CPU Instruction Pointer when triggered. */ | |
#if LJ_PROFILE_SIGPROF | |
struct sigaction oldsa; /* Previous SIGPROF state. */ | |
#elif LJ_PROFILE_PTHREAD | |
@@ -144,13 +146,15 @@ void LJ_FASTCALL lj_profile_interpreter(lua_State *L) | |
uint8_t mask; | |
profile_lock(ps); | |
mask = (g->hookmask & ~HOOK_PROFILE); | |
+ printf("lj_profile_interpreter\n"); | |
if (!(mask & HOOK_VMEVENT)) { | |
int samples = ps->samples; | |
ps->samples = 0; | |
g->hookmask = HOOK_VMEVENT; | |
lj_dispatch_update(g); | |
profile_unlock(ps); | |
- ps->cb(ps->data, L, samples, ps->vmstate); /* Invoke user callback. */ | |
+ printf("Calling cb with ps->ip %p\n", (void*)ps->ip); | |
+ ps->cb(ps->data, L, samples, ps->vmstate, ps->ip); /* Invoke user callback. */ | |
profile_lock(ps); | |
mask |= (g->hookmask & HOOK_PROFILE); | |
} | |
@@ -160,12 +164,13 @@ void LJ_FASTCALL lj_profile_interpreter(lua_State *L) | |
} | |
/* Trigger profile hook. Asynchronous call from OS-specific profile timer. */ | |
-static void profile_trigger(ProfileState *ps) | |
+static void profile_trigger(ProfileState *ps, uint64_t ip) | |
{ | |
global_State *g = ps->g; | |
uint8_t mask; | |
profile_lock(ps); | |
ps->samples++; /* Always increment number of samples. */ | |
+ ps->ip = ip; | |
mask = g->hookmask; | |
if (!(mask & (HOOK_PROFILE|HOOK_VMEVENT))) { /* Set profile hook. */ | |
int st = g->vmstate; | |
@@ -176,6 +181,13 @@ static void profile_trigger(ProfileState *ps) | |
g->hookmask = (mask | HOOK_PROFILE); | |
lj_dispatch_update(g); | |
} | |
+ /* | |
+ else { | |
+ int samples = ps->samples; | |
+ ps->samples = 0; | |
+ ps->cb(ps->data, g, samples, ps->vmstate, ps->ip); | |
+ } | |
+*/ | |
profile_unlock(ps); | |
} | |
@@ -184,13 +196,13 @@ static void profile_trigger(ProfileState *ps) | |
#if LJ_PROFILE_SIGPROF | |
/* SIGPROF handler. */ | |
-static void profile_signal(int sig) | |
+static void profile_signal(int sig, siginfo_t *info, void *data) | |
{ | |
UNUSED(sig); | |
- profile_trigger(&profile_state); | |
+ uint64_t ip = (uint64_t)((ucontext_t*)data)->uc_mcontext.gregs[REG_RIP]; | |
+ profile_trigger(&profile_state, ip); | |
} | |
- | |
static int perf_event_open(struct perf_event_attr *attr, | |
pid_t pid, int cpu, int group_fd, | |
unsigned long flags) | |
@@ -324,8 +336,8 @@ static void register_prof_events(ProfileState *ps) | |
static void profile_timer_start(ProfileState *ps) | |
{ | |
struct sigaction sa = { | |
- .sa_flags = SA_RESTART, | |
- .sa_handler = profile_signal | |
+ .sa_flags = SA_RESTART|SA_SIGINFO, | |
+ .sa_sigaction = profile_signal | |
}; | |
sigemptyset(&sa.sa_mask); | |
diff --git a/lib/luajit/src/luajit.h b/lib/luajit/src/luajit.h | |
index 9604185..fe67cd4 100644 | |
--- a/lib/luajit/src/luajit.h | |
+++ b/lib/luajit/src/luajit.h | |
@@ -29,6 +29,7 @@ | |
#define _LUAJIT_H | |
#include "lua.h" | |
+#include <stdint.h> | |
#define LUAJIT_VERSION "LuaJIT 2.1.0-beta1" | |
#define LUAJIT_VERSION_NUM 20100 /* Version 2.1.0 = 02.01.00. */ | |
@@ -66,7 +67,8 @@ LUA_API int luaJIT_setmode(lua_State *L, int idx, int mode); | |
/* Low-overhead profiling API. */ | |
typedef void (*luaJIT_profile_callback)(void *data, lua_State *L, | |
- int samples, int vmstate); | |
+ int samples, int vmstate, | |
+ uint64_t ip); | |
LUA_API void luaJIT_profile_start(lua_State *L, const char *mode, | |
luaJIT_profile_callback cb, void *data); | |
LUA_API void luaJIT_profile_stop(lua_State *L); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment