Skip to content

Instantly share code, notes, and snippets.

@lukego
Last active September 23, 2015 07:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lukego/d801cc7ad5fa68d884fb to your computer and use it in GitHub Desktop.
Save lukego/d801cc7ad5fa68d884fb to your computer and use it in GitHub Desktop.
LuaJIT profiler extension to count loops of traces separately [draft]
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