diff options
| author | Mike Pall <mike> | 2010-05-01 04:27:14 +0200 |
|---|---|---|
| committer | Mike Pall <mike> | 2010-05-01 04:27:14 +0200 |
| commit | 8fa1db826c095adcc45d961e6f6870406d69d49d (patch) | |
| tree | ef3f517361fa4dadbf1bbefa0d3d35323a5c0068 /src | |
| parent | f28a42c9239142441bf3e3149f5d76efab71aac2 (diff) | |
| download | luajit-8fa1db826c095adcc45d961e6f6870406d69d49d.tar.gz luajit-8fa1db826c095adcc45d961e6f6870406d69d49d.tar.bz2 luajit-8fa1db826c095adcc45d961e6f6870406d69d49d.zip | |
Create symbol table of JIT-compiled code for use with Linux perf tools.
Enable with: -DLUAJIT_USE_PERFTOOLS
Diffstat (limited to 'src')
| -rw-r--r-- | src/lj_trace.c | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/src/lj_trace.c b/src/lj_trace.c index 8419c9bb..fc531a19 100644 --- a/src/lj_trace.c +++ b/src/lj_trace.c | |||
| @@ -81,6 +81,44 @@ static TraceNo trace_findfree(jit_State *J) | |||
| 81 | memcpy(p, J->cur.field, J->cur.szfield*sizeof(tp)); \ | 81 | memcpy(p, J->cur.field, J->cur.szfield*sizeof(tp)); \ |
| 82 | p += J->cur.szfield*sizeof(tp); | 82 | p += J->cur.szfield*sizeof(tp); |
| 83 | 83 | ||
| 84 | #ifdef LUAJIT_USE_PERFTOOLS | ||
| 85 | /* | ||
| 86 | ** Create symbol table of JIT-compiled code. For use with Linux perf tools. | ||
| 87 | ** Example usage: | ||
| 88 | ** perf record -f -e cycles luajit test.lua | ||
| 89 | ** perf report -s symbol | ||
| 90 | ** rm perf.data /tmp/perf-*.map | ||
| 91 | */ | ||
| 92 | #include <stdio.h> | ||
| 93 | #include <unistd.h> | ||
| 94 | |||
| 95 | static void perftools_addtrace(GCtrace *T) | ||
| 96 | { | ||
| 97 | static FILE *fp; | ||
| 98 | GCproto *pt = &gcref(T->startpt)->pt; | ||
| 99 | uintptr_t pcofs = (uintptr_t)(T->snap[0].mapofs+T->snap[0].nent); | ||
| 100 | const BCIns *startpc = snap_pc(T->snapmap[pcofs]); | ||
| 101 | const char *name = strdata(proto_chunkname(pt)); | ||
| 102 | BCLine lineno; | ||
| 103 | if (name[0] == '@' || name[0] == '=') | ||
| 104 | name++; | ||
| 105 | else | ||
| 106 | name = "(string)"; | ||
| 107 | if (startpc >= proto_bc(pt) && startpc < proto_bc(pt) + pt->sizebc) | ||
| 108 | lineno = proto_line(pt, proto_bcpos(pt, startpc)); | ||
| 109 | else | ||
| 110 | lineno = proto_line(pt, 0); /* Wrong, but better than nothing. */ | ||
| 111 | if (!fp) { | ||
| 112 | char fname[40]; | ||
| 113 | sprintf(fname, "/tmp/perf-%d.map", getpid()); | ||
| 114 | if (!(fp = fopen(fname, "w"))) return; | ||
| 115 | setlinebuf(fp); | ||
| 116 | } | ||
| 117 | fprintf(fp, "%lx %x TRACE_%d::%s:%u\n", | ||
| 118 | (long)T->mcode, T->szmcode, T->traceno, name, lineno); | ||
| 119 | } | ||
| 120 | #endif | ||
| 121 | |||
| 84 | /* Save current trace by copying and compacting it. */ | 122 | /* Save current trace by copying and compacting it. */ |
| 85 | static void trace_save(jit_State *J) | 123 | static void trace_save(jit_State *J) |
| 86 | { | 124 | { |
| @@ -105,6 +143,9 @@ static void trace_save(jit_State *J) | |||
| 105 | setgcrefp(J->trace[T->traceno], T); | 143 | setgcrefp(J->trace[T->traceno], T); |
| 106 | lj_gc_barriertrace(J2G(J), T->traceno); | 144 | lj_gc_barriertrace(J2G(J), T->traceno); |
| 107 | lj_gdbjit_addtrace(J, T); | 145 | lj_gdbjit_addtrace(J, T); |
| 146 | #ifdef LUAJIT_USE_PERFTOOLS | ||
| 147 | perftools_addtrace(T); | ||
| 148 | #endif | ||
| 108 | } | 149 | } |
| 109 | 150 | ||
| 110 | void LJ_FASTCALL lj_trace_free(global_State *g, GCtrace *T) | 151 | void LJ_FASTCALL lj_trace_free(global_State *g, GCtrace *T) |
