Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
stapxx/tapset/luajit.sxx
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
832 lines (654 sloc)
19.4 KB
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
| // module luajit | |
| @use nginx.lua | |
| $*pt := @cast(pt, "GCproto", "$^libluajit_path") | |
| //@define LJ_TLIGHTUD %( 4294967292 %) | |
| @define LJ_TLIGHTUD %( 4294901760 %) | |
| @define LJ_TSTR %( 4294967291 %) | |
| @define LJ_TUDATA %( 4294967283 %) | |
| @define LJ_TFUNC %( 4294967287 %) | |
| @define TSTR %( 4 %) | |
| @define TUPVAL %( 5 %) | |
| @define TTHREAD %( 6 %) | |
| @define TPROTO %( 7 %) | |
| @define TFUNC %( 8 %) | |
| @define TTRACE %( 9 %) | |
| @define TCDATA %( 10 %) | |
| @define TTAB %( 11 %) | |
| @define TUDATA %( 12 %) | |
| @define CTSHIFT_NUM %( 28 %) | |
| @define CT_HASSIZE %( 5 %) | |
| @define CT_ATTRIB %( 8 %) | |
| @define CTMASK_CID %( 0xffff %) | |
| @define FF_LUA %( 0 %) | |
| @define FF_C %( 1 %) | |
| @define FRAME_LUA %( 0 %) | |
| @define FRAME_CONT %( 2 %) | |
| @define FRAME_TYPE %( 3 %) | |
| @define FRAME_P %( 4 %) | |
| @define FRAME_TYPEP %( (@FRAME_TYPE|@FRAME_P) %) | |
| @define NO_BCPOS %( ~0 %) | |
| @define sizeof_GCtab %( &@cast(0, "GCtab", "$^libluajit_path")[1] %) | |
| @define sizeof_TValue %( &@cast(0, "TValue", "$^libluajit_path")[1] %) | |
| @define sizeof_lua_State %( &@cast(0, "struct lua_State", "$^libluajit_path")[1] %) | |
| @define sizeof_GCfunc %( &@cast(0, "union GCfunc", "$^libluajit_path")[1] %) | |
| @define sizeof_GCupval %( &@cast(0, "GCupval", "$^libluajit_path")[1] %) | |
| @define sizeof_GCstr %( &@cast(0, "GCstr", "$^libluajit_path")[1] %) | |
| @define sizeof_GCudata %( &@cast(0, "GCudata", "$^libluajit_path")[1] %) | |
| @define sizeof_Node %( &@cast(0, "Node", "$^libluajit_path")[1] %) | |
| @define sizeof_GCfuncC %( &@cast(0, "GCfuncC", "$^libluajit_path")[1] %) | |
| @define sizeof_GCfuncL %( &@cast(0, "GCfuncL", "$^libluajit_path")[1] %) | |
| @define sizeof_GCRef %( &@cast(0, "GCRef", "$^libluajit_path")[1] %) | |
| @define sizeof_GCproto %( &@cast(0, "GCproto", "$^libluajit_path")[1] %) | |
| @define sizeof_GCtrace %( &@cast(0, "GCtrace", "$^libluajit_path")[1] %) | |
| @define sizeof_GCcdata %( &@cast(0, "GCcdata", "$^libluajit_path")[1] %) | |
| @define sizeof_IRIns %( &@cast(0, "IRIns", "$^libluajit_path")[1] %) | |
| @define sizeof_IRRef %( &@cast(0, "IRRef", "$^libluajit_path")[1] %) | |
| @define sizeof_SnapShot %( &@cast(0, "SnapShot", "$^libluajit_path")[1] %) | |
| @define sizeof_SnapEntry %( &@cast(0, "SnapEntry", "$^libluajit_path")[1] %) | |
| @define sizeof_K64Array %( &@cast(0, "K64Array", "$^libluajit_path")[1] %) | |
| @define sizeof_ptr %( &@cast(0, "global_State", "$^libluajit_path")->strmask %) | |
| @define sizeof_GCcdataVar %( &@cast(0, "GCcdataVar", "$^libluajit_path")[1] %) | |
| @define sizeof_BCIns %( &@cast(0, "BCIns", "$^libluajit_path")[1] %) | |
| @define strdata(s) %( | |
| (@s + @sizeof_GCstr) | |
| %) | |
| @define frame_gc(frame) %( | |
| @cast(@frame, "TValue", "$^libluajit_path")->fr->func->gcptr32 | |
| %) | |
| @define frame_ftsz(tv) %( | |
| @cast(@tv, "TValue", "$^libluajit_path")->fr->tp->ftsz | |
| %) | |
| @define frame_type(f) %( | |
| (@frame_ftsz(@f) & @FRAME_TYPE) | |
| %) | |
| @define frame_typep(f) %( | |
| (@frame_ftsz(@f) & @FRAME_TYPEP) | |
| %) | |
| @define frame_islua(f) %( | |
| (@frame_type(@f) == @FRAME_LUA) | |
| %) | |
| @define frame_iscont(f) %( | |
| (@frame_typep(@f) == @FRAME_CONT) | |
| %) | |
| @define frame_pc(tv) %( | |
| @cast(@tv, "TValue", "$^libluajit_path")->fr->tp->pcr->ptr32 | |
| %) | |
| @define frame_contpc(f) %( | |
| (@frame_pc(@f) - 1 * @sizeof_BCIns) | |
| %) | |
| @define bc_a(i) %( | |
| ((@i >> 8) & 0xff) | |
| %) | |
| @define frame_prevl(f) %( | |
| (@f - (1 + @bc_a(user_uint32(@frame_pc(@f) - 4))) * @sizeof_TValue) | |
| %) | |
| @define FRAME_VARG %( 3 %) | |
| @define frame_isvarg(f) %( | |
| (@frame_typep(@f) == @FRAME_VARG) | |
| %) | |
| @define frame_sized(f) %( | |
| (@frame_ftsz(@f) & ~@FRAME_TYPEP) | |
| %) | |
| @define frame_prevd(f) %( | |
| (@f - @frame_sized(@f)) | |
| %) | |
| @define isluafunc(fn) %( | |
| (@cast(@fn, "GCfunc", "$^libluajit_path")->c->ffid == @FF_LUA) | |
| %) | |
| @define isffunc(fn) %( | |
| (@cast(@fn, "GCfunc", "$^libluajit_path")->c->ffid > @FF_C) | |
| %) | |
| @define funcproto(fn) %( | |
| (@cast(@fn, "GCfunc", "$^libluajit_path")->l->pc->ptr32 - @sizeof_GCproto) | |
| %) | |
| @define proto_bc(pt) %( | |
| (@pt + @sizeof_GCproto) | |
| %) | |
| @define proto_bcpos(pt, pc) %( | |
| ((@pc - @proto_bc(@pt)) / @sizeof_BCIns) | |
| %) | |
| @define proto_lineinfo(pt) %( | |
| @cast(@pt, "GCproto", "$^libluajit_path")->lineinfo->ptr32 | |
| %) | |
| global luajit_cfunc_cache | |
| function luajit_frame_func(f) { | |
| gco = @frame_gc(f) | |
| $*gco := @cast(gco, "GCobj", "$^libluajit_path") | |
| return &$*gco->fn | |
| } | |
| function luajit_G(L) | |
| { | |
| $*L := @cast(L, "lua_State", "$^libluajit_path") | |
| return $*L->glref->ptr32 | |
| } | |
| function luajit_gcref(r) | |
| { | |
| $*r := @cast(r, "GCRef", "$^libluajit_path") | |
| return $*r->gcptr32 | |
| } | |
| function luajit_objlen(o, gct, g) | |
| { | |
| $*o := @cast(o, "GCobj", "$^libluajit_path") | |
| if (gct == @TSTR) { | |
| /* | |
| if ($*o->str->len == 0) { | |
| printf("empty string found.\n") | |
| } | |
| */ | |
| return $*o->str->len + 1 + @sizeof_GCstr | |
| } | |
| if (gct == @TTAB) { | |
| t = &$*o->tab | |
| $*t := @cast(t, "GCtab", "$^libluajit_path") | |
| asize = $*t->asize | |
| hmask = $*t->hmask | |
| n = 0 | |
| if (hmask > 0) { | |
| n += @sizeof_Node * (hmask + 1) | |
| } | |
| if (asize > 0 && $*t->colo <= 0) { | |
| n += @sizeof_TValue * asize | |
| } | |
| if ($*t->colo) { | |
| n += ($*t->colo & 0x7f) * @sizeof_TValue + @sizeof_GCtab | |
| } else { | |
| n += @sizeof_GCtab | |
| } | |
| return n | |
| } | |
| if (gct == @TUDATA) { | |
| return $*o->ud->len + @sizeof_GCudata | |
| } | |
| if (gct == @TPROTO) { | |
| return $*o->pt->sizept | |
| } | |
| if (gct == @TTHREAD) { | |
| L = &$*o->th | |
| //printf("open upval: %p\n", luajit_gcref(&$*L->openupval)) | |
| //printf("lua_State: %d\n", @sizeof_lua_State) | |
| n = @sizeof_lua_State + $*L->stacksize * @sizeof_TValue | |
| p = &$*L->openupval | |
| while (p) { | |
| o = luajit_gcref(p) | |
| if (o == 0) { | |
| break; | |
| } | |
| $*o := @cast(o, "GCobj", "$^libluajit_path") | |
| gct = $*o->gch->gct | |
| size = luajit_objlen(o, gct, g) | |
| //printf("%s: %d\n", typenames[@TSTR], size) | |
| n += size | |
| p = &$*o->gch->nextgc | |
| } | |
| return n | |
| } | |
| if (gct == @TFUNC) { | |
| fn = &$*o->fn | |
| $*fn := @cast(fn, "GCfunc", "$^libluajit_path"); | |
| if (@isluafunc(fn)) { | |
| n = $*fn->l->nupvalues | |
| //n = 0 | |
| return @sizeof_GCfuncL - @sizeof_GCRef + @sizeof_GCRef * n | |
| } | |
| n = $*fn->c->nupvalues | |
| //n = 0 | |
| return @sizeof_GCfuncC - @sizeof_TValue + @sizeof_TValue * n | |
| } | |
| if (gct == @TUPVAL) { | |
| return @sizeof_GCupval | |
| } | |
| if (gct == @TTRACE) { | |
| T = o | |
| $*T := @cast(T, "GCtrace", "$^libluajit_path") | |
| return ((@sizeof_GCtrace + 7) & ~7) | |
| + ($*T->nins - $*T->nk) * @sizeof_IRIns | |
| + $*T->nsnap * @sizeof_SnapShot | |
| + $*T->nsnapmap * @sizeof_SnapEntry | |
| } | |
| $*g := @cast(g, "global_State", "$^libluajit_path") | |
| if (gct == @TCDATA) { | |
| cd = o | |
| $*cd := @cast(cd, "GCcdata", "$^libluajit_path") | |
| if ($*cd->marked & 0x80) { | |
| /* cdata is a vector */ | |
| cdatav = cd - @sizeof_GCcdataVar | |
| $*cdatav := @cast(cdatav, "GCcdataVar", "$^libluajit_path") | |
| return $*cdatav->len + $*cdatav->extra | |
| } | |
| /* cdata is not a vector */ | |
| cts = $*g->ctype_state->ptr32 | |
| $*cts := @cast(cts, "CTState", "$^libluajit_path") | |
| id = $*cd->ctypeid | |
| ct = &$*cts->tab[id] | |
| $*ct := @cast(ct, "CType", "$^libluajit_path") | |
| while (($*ct->info >> @CTSHIFT_NUM) == @CT_ATTRIB) { | |
| //printf("XXX skipping c type attribute\n") | |
| ct = &$*cts->tab[$*ct->info & @CTMASK_CID] | |
| } | |
| if (($*ct->info >> @CTSHIFT_NUM) <= @CT_HASSIZE) { | |
| sz = $*ct->size | |
| } else { | |
| sz = @sizeof_ptr | |
| } | |
| //printf("GCcdata size: %d\n", @sizeof_GCcdata) | |
| return @sizeof_GCcdata + sz | |
| } | |
| return 0 | |
| } | |
| function luajit_jit_state_size(J) | |
| { | |
| $*J := @cast(J, "jit_State", "$^libluajit_path") | |
| ir_k64_size = 0 | |
| // In the newer revision of luajit, 64-bit constants are represented as an | |
| // array of TValue. Uncomment following code if the luajit being used | |
| // is using linked list to represent 64-bit constants. As the 64-bit | |
| // constants don't take lots of memory, it does not seems to be a big deal | |
| // if you don't uncomment following code for the older luajit. | |
| // | |
| /* | |
| $*k := @cast(k, "K64Array", "$^libluajit_path") | |
| for (k = $*J->k64->ptr32; k; ) { | |
| ir_k64_size += @sizeof_K64Array | |
| k = $*k->next->ptr32 | |
| } | |
| if (ir_k64_size) { | |
| //printf("64-bit constants: %d\n", ir_k64_size) | |
| } | |
| */ | |
| sizesnapmap = $*J->sizesnapmap * @sizeof_SnapEntry | |
| if (sizesnapmap) { | |
| //printf("JIT snap map buffer size: %d\n", sizesnapmap) | |
| } | |
| sizesnap = $*J->sizesnap * @sizeof_SnapShot | |
| if (sizesnap) { | |
| //printf("JIT snap buffer size: %d\n", sizesnap) | |
| } | |
| sizeirbuf = ($*J->irtoplim - $*J->irbotlim) * @sizeof_IRIns | |
| if (sizeirbuf) { | |
| //printf("JIT IR buffer size: %d\n", sizeirbuf) | |
| } | |
| sizetrace = $*J->sizetrace * @sizeof_GCRef | |
| if (sizetrace) { | |
| //printf("JIT trace array size: %d\n", sizetrace) | |
| } | |
| return ir_k64_size + sizesnapmap + sizesnap + sizeirbuf + sizetrace | |
| } | |
| /* returns a TValue* pointer */ | |
| function luajit_index2adr(L, idx) | |
| { | |
| if (idx > 0) { | |
| o = $*L->base + (idx - 1) * @sizeof_TValue | |
| return o < $*L->top ? o : 0 | |
| } | |
| top = $*L->top | |
| if (idx != 0 && -idx <= top - $*L->base) { | |
| return top + idx * @sizeof_TValue; | |
| } | |
| return 0 | |
| } | |
| /* convert GCstr to stap string */ | |
| function luajit_unbox_gcstr(gcs) | |
| { | |
| if (gcs == 0) { | |
| return "" | |
| } | |
| $*gcs := @cast(gcs, "GCstr", "$^libluajit_path") | |
| src = @strdata(gcs) | |
| return user_string_n_warn(src, $*gcs->len) | |
| } | |
| function luajit_tostring(L, idx) | |
| { | |
| $*o := @cast(o, "TValue", "$^libluajit_path") | |
| o = luajit_index2adr(L, idx) | |
| if (o == 0) { | |
| return "<nil>" | |
| } | |
| if ($*o->it == @LJ_TSTR) { | |
| gco = $*o->gcr->gcptr32 | |
| $*gco := @cast(gco, "GCobj", "$^libluajit_path") | |
| s = &$*gco->str | |
| $*s := @cast(s, "GCstr", "$^libluajit_path") | |
| return user_string_n(s + @sizeof_GCstr, $*s->len) | |
| } | |
| return "<unknown>" | |
| } | |
| function luajit_tostringlen(L, idx) | |
| { | |
| $*o := @cast(o, "TValue", "$^libluajit_path") | |
| o = luajit_index2adr(L, idx) | |
| if (o == 0) { | |
| return -1 | |
| } | |
| if ($*o->it == @LJ_TSTR) { | |
| gco = $*o->gcr->gcptr32 | |
| $*gco := @cast(gco, "GCobj", "$^libluajit_path") | |
| s = &$*gco->str | |
| $*s := @cast(s, "GCstr", "$^libluajit_path") | |
| return $*s->len | |
| } | |
| return -1 | |
| } | |
| function luajit_touserdata(L, idx) | |
| { | |
| $*o := @cast(o, "TValue", "$^libluajit_path") | |
| o = luajit_index2adr(L, idx) | |
| if (o == 0) { | |
| return 0 | |
| } | |
| //printf("udata type: %d (%d)\n", $*o->it, ($*o->it >> 15)) | |
| if ($*o->it == @LJ_TUDATA) { | |
| gco = $*o->gcr->gcptr32 | |
| ud = &$*gco->ud | |
| $*ud := @cast(ud, "GCudata", "$^libluajit_path") | |
| return ud + @sizeof_GCudata | |
| } | |
| if ($*o->it == @LJ_TLIGHTUD) { | |
| return $*o->u64 & 0x7fffffffffff | |
| } | |
| return 0 | |
| } | |
| function luajit_proto_chunkname(pt) { | |
| gco = $*pt->chunkname->gcptr32 | |
| return &$*gco->str | |
| } | |
| function luajit_debug_framepc(L, T, fn, pt, nextframe) { | |
| //printf("debug framepc: L=%p, fn=%p, nextframe = %p\\n", L, fn, nextframe) | |
| if (nextframe == 0) { | |
| return @NO_BCPOS | |
| } | |
| if (@frame_islua(nextframe)) { | |
| ins = @frame_pc(nextframe); | |
| //printf("frame is lua, ins = %p\\n", ins) | |
| } else if (@frame_iscont(nextframe)) { | |
| //println("frame is cont") | |
| ins = @frame_contpc(nextframe) | |
| } else { | |
| /* TODO: add support for cframe */ | |
| } | |
| //printf("debug framepc: ins = %p\\n", ins) | |
| pos = @proto_bcpos(pt, ins) - 1; | |
| sizebc = $*pt->sizebc | |
| if (pos > sizebc) { | |
| //printf("Undo the effects of lj_trace_exit for JLOOP.\n") | |
| if (!T) { | |
| T = ins - 1 * @sizeof_BCIns - &@cast(0, "GCtrace", "$^libluajit_path")->startins; | |
| } | |
| //printf("startpc: %d\n", $*T->startpc->ptr32) | |
| pos = @proto_bcpos(pt, $*T->startpc->ptr32); | |
| //printf("Found adjusted position: %d\n", pos) | |
| } | |
| return pos; | |
| } | |
| function luajit_debug_line(pt, pc) | |
| { | |
| lineinfo = @proto_lineinfo(pt) | |
| //printf("lj_debug_line: lineinfo = %p, %x <= %x\\n", lineinfo, | |
| //pc, $pt->sizebc) | |
| sizebc = $*pt->sizebc | |
| if (pc <= sizebc && lineinfo) { | |
| first = $*pt->firstline | |
| if (pc == sizebc) { | |
| return first + $*pt->numline | |
| } | |
| if (pc-- == 0) { | |
| return first | |
| } | |
| if ($*pt->numline < 256) { | |
| return first + @cast(lineinfo, "uint8_t", "$^libluajit_path")[pc] | |
| } | |
| if ($*pt->numline < 65536) { | |
| return first + @cast(lineinfo, "uint16_t", "$^libluajit_path")[pc] | |
| } | |
| return first + @cast(lineinfo, "uint32_t", "$^libluajit_path")[pc] | |
| } | |
| return -1 | |
| } | |
| function luajit_debug_frameline(L, T, fn, pt, nextframe) | |
| { | |
| pc = luajit_debug_framepc(L, T, fn, pt, nextframe) | |
| if (pc != @NO_BCPOS) { | |
| if (pc <= $*pt->sizebc) { | |
| return luajit_debug_line(pt, pc) | |
| } | |
| } | |
| return -1 | |
| } | |
| function luajit_debug_dumpstack(L, T, depth, base, simple) | |
| { | |
| level = 0 | |
| dir = 1 | |
| if (depth < 0) { | |
| level = ~depth | |
| depth = dir = -1 | |
| } | |
| bt = "" | |
| while (level != depth) { | |
| /* lj_debug_frame(L, level, &size) {{{ */ | |
| bot = $*L->stack->ptr32 | |
| found_frame = 0 | |
| tmp_level = level | |
| /* Traverse frames backwards. */ | |
| for (nextframe = frame = base - @sizeof_TValue; frame > bot; ) { | |
| if (@frame_gc(frame) == L) { | |
| tmp_level++ | |
| } | |
| if (tmp_level-- == 0) { | |
| size = (nextframe - frame) / @sizeof_TValue | |
| found_frame = 1 | |
| break | |
| } | |
| nextframe = frame | |
| if (@frame_islua(frame)) { | |
| frame = @frame_prevl(frame) | |
| } else { | |
| if (@frame_isvarg(frame)) { | |
| tmp_level++; /* Skip vararg pseudo-frame. */ | |
| } | |
| frame = @frame_prevd(frame); | |
| } | |
| } | |
| if (!found_frame) { | |
| frame = 0 | |
| size = tmp_level | |
| } | |
| /* }}} */ | |
| if (frame) { | |
| //nextframe = size ? frame + size * @sizeof_TValue : 0 | |
| fn = luajit_frame_func(frame) | |
| if (fn == 0) { | |
| return "" | |
| } | |
| if (@isluafunc(fn)) { | |
| pt = @funcproto(fn) | |
| if (simple) { | |
| line = $*pt->firstline | |
| } else { | |
| line = luajit_debug_frameline(L, T, fn, pt, nextframe) | |
| if (line < 0) { | |
| line = $*pt->firstline | |
| //printf("using firstline %d\n", line) | |
| } else { | |
| //printf("GOT the lineno %d\n", line) | |
| } | |
| } | |
| name = luajit_proto_chunkname(pt) /* GCstr *name */ | |
| if (name == 0) { | |
| return "" | |
| } | |
| path = luajit_unbox_gcstr(name) | |
| bt .= sprintf("%s:%d\n", path, line) | |
| } else if (@isffunc(fn)) { | |
| bt .= sprintf("builtin#%d\n", $*fn->c->ffid) | |
| } else { | |
| /* C function */ | |
| cfunc = $*fn->c->f | |
| sym = luajit_cfunc_cache[cfunc] | |
| if (sym == "") { | |
| sym = sprintf("C:%s\n", usymname(cfunc)) | |
| luajit_cfunc_cache[cfunc] = sym | |
| } | |
| bt .= sym | |
| } | |
| } else if (dir == 1) { | |
| break | |
| } else { | |
| level -= size | |
| } | |
| level += dir | |
| } | |
| return bt | |
| } | |
| function luajit_cur_thread(g) | |
| { | |
| $*g := @cast(g, "global_State", "$^libluajit_path") | |
| gco = $*g->cur_L->gcptr32 | |
| if (gco == 0) { | |
| return 0 | |
| } | |
| return &$*gco->th | |
| } | |
| function luajit_get_trace(g, traceno) | |
| { | |
| GG = g - &@cast(0, "GG_State", "$^libluajit_path")->g | |
| $*GG := @cast(GG, "GG_State", "$^libluajit_path") | |
| J = &$*GG->J | |
| $*J := @cast(J, "jit_State", "$^libluajit_path") | |
| if (J == 0) { | |
| return 0 | |
| } | |
| return $*J->trace[traceno]->gcptr32 | |
| } | |
| function luajit_trace_starting_func(g, trace) | |
| { | |
| $*trace := @cast(trace, "GCtrace", "$^libluajit_path") | |
| gco = $*trace->startpt->gcptr32 | |
| if (gco == 0) { | |
| return "" | |
| } | |
| pt = &$*gco->pt | |
| firstline = $*pt->firstline | |
| name = luajit_proto_chunkname(pt) /* GCstr *name */ | |
| path = luajit_unbox_gcstr(name) | |
| return sprintf("%s:%d", path, firstline) | |
| } | |
| function luajit_print_backtrace(simple) | |
| { | |
| if (@defined(@var("globalL", "$^exec_path"))) { | |
| mL = @var("globalL", "$^exec_path") | |
| } else { | |
| mL = ngx_lua_get_main_lua_vm() | |
| } | |
| if (mL == 0) { | |
| return "" | |
| } | |
| g = luajit_G(mL) | |
| if (g == 0) { | |
| return "" | |
| } | |
| L = luajit_cur_thread(g) | |
| if (L == 0) { | |
| return "" | |
| } | |
| return luajit_backtrace(L, g, simple) | |
| } | |
| function luajit_backtrace(L, g, simple) | |
| { | |
| bt = "" | |
| vmstate = $*g->vmstate | |
| if (vmstate >= 0 || (vmstate == -3 && $*g->jit_base->ptr32)) { | |
| /* compiled Lua code */ | |
| T = luajit_get_trace(g, vmstate) | |
| if (T) { | |
| if (simple) { | |
| func = luajit_trace_starting_func(g, T) | |
| if (func != "") { | |
| bt .= sprintf("T:%s\n", func) | |
| } | |
| } else { | |
| //printf("start pc: %d\n", $*T->startpc->ptr32) | |
| } | |
| #warn(sprintf("bt: %s", bt)) | |
| } | |
| base = $*g->jit_base->ptr32 | |
| if (!base) { | |
| return bt | |
| } | |
| bt .= luajit_debug_dumpstack(L, T, $^arg_depth :default(30), base, simple) | |
| /* | |
| if (bt != "") { | |
| warn(sprintf("JIT backtrace: %s\n", bt)) | |
| } | |
| */ | |
| /* | |
| if (vmstate == -3) { | |
| printf("HIT JIT GC: %s===\n", bt) | |
| } | |
| */ | |
| } else { | |
| if (vmstate == -1 && !$*L->cframe) { | |
| return "" | |
| } | |
| if (vmstate == -1 || vmstate == -2 || vmstate == -3) { | |
| base = $*L->base | |
| bt .= luajit_debug_dumpstack(L, 0, $^arg_depth, base, simple) | |
| } | |
| } | |
| return bt | |
| } | |
| function luajit_vm_state(g) | |
| { | |
| return $*g->vmstate | |
| } | |
| function luajit_find_gcstr(g, str) | |
| { | |
| len = strlen(str) | |
| strmask = $*g->strmask | |
| strnum = $*g->strnum | |
| strhash = $*g->strhash | |
| $*strhash := @cast(strhash, "GCRef", "$^libluajit_path") | |
| ret = 0 | |
| n = 0 | |
| done = 0 | |
| for (i = 0; i <= strmask; i++) { | |
| p = &$*strhash[i] | |
| while (p) { | |
| o = luajit_gcref(p) | |
| if (o == 0) { | |
| break | |
| } | |
| $*o := @cast(o, "GCobj", "$^libluajit_path") | |
| if ($*o->str->len == len) { | |
| gcs = &$*o->str | |
| s = luajit_unbox_gcstr(gcs) | |
| if (s == str) { | |
| done = 1 | |
| ret = gcs | |
| break | |
| } | |
| } | |
| if (++n == strnum) { | |
| done = 1 | |
| break | |
| } | |
| p = &$*o->gch->nextgc | |
| } | |
| if (done) { | |
| break | |
| } | |
| } | |
| return ret | |
| } | |
| function luajit_bucket_depth(p) | |
| { | |
| n = 0 | |
| while (p) { | |
| $*o := @cast(o, "GCobj", "$^libluajit_path") | |
| o = luajit_gcref(p) | |
| if (o == 0) { | |
| break | |
| } | |
| n++; | |
| p = &$*o->gch->nextgc | |
| } | |
| return n | |
| } |