/* Throw error. Find catch frame, unwind stack and continue. */ LJ_NOINLINE void LJ_FASTCALL lj_err_throw(lua_State *L, int errcode) { global_State *g = G(L); lj_trace_abort(g); setgcrefnull(g->jit_L); L->status = 0; #if LJ_UNWIND_EXT err_raise_ext(errcode); /* ** A return from this function signals a corrupt C stack that cannot be ** unwound. We have no choice but to call the panic function and exit. ** ** Usually this is caused by a C function without unwind information. ** This should never happen on x64, but may happen if you've manually ** enabled LUAJIT_UNWIND_EXTERNAL and forgot to recompile *every* ** non-C++ file with -funwind-tables. */ if (G(L)->panic) G(L)->panic(L); #else { void *cf = err_unwind(L, NULL, errcode); if (cframe_unwind_ff(cf)) lj_vm_unwind_ff(cframe_raw(cf)); else lj_vm_unwind_c(cframe_raw(cf), errcode); } #endif exit(EXIT_FAILURE); }
/* This function can be called asynchronously (e.g. during a signal). */ LUA_API int lua_sethook(lua_State *L, lua_Hook func, int mask, int count) { global_State *g = G(L); mask &= HOOK_EVENTMASK; if (func == NULL || mask == 0) { mask = 0; func = NULL; } /* Consistency. */ g->hookf = func; g->hookcount = g->hookcstart = (int32_t)count; g->hookmask = (uint8_t)((g->hookmask & ~HOOK_EVENTMASK) | mask); lj_trace_abort(g); /* Abort recording on any hook change. */ lj_dispatch_update(g); return 1; }
LUALIB_API int luaL_fileresult(lua_State *L, int stat, const char *fname) { if (stat) { setboolV(L->top++, 1); return 1; } else { int en = errno; /* Lua API calls may change this value. */ setnilV(L->top++); if (fname) lua_pushfstring(L, "%s: %s", fname, strerror(en)); else lua_pushfstring(L, "%s", strerror(en)); setintV(L->top++, en); lj_trace_abort(G(L)); return 3; } }
/* Call a hook. */ static void callhook(lua_State *L, int event, BCLine line) { global_State *g = G(L); lua_Hook hookf = g->hookf; if (hookf && !hook_active(g)) { lua_Debug ar; lj_trace_abort(g); /* Abort recording on any hook call. */ ar.event = event; ar.currentline = line; ar.i_ci = cast_int((L->base-1) - L->stack); /* Top frame, nextframe=NULL. */ lj_state_checkstack(L, 1+LUA_MINSTACK); hook_enter(g); hookf(L, &ar); lua_assert(hook_active(g)); hook_leave(g); } }
/* Runtime error. */ LJ_NOINLINE void lj_err_run(lua_State *L) { ptrdiff_t ef = finderrfunc(L); if (ef) { TValue *errfunc = restorestack(L, ef); TValue *top = L->top; lj_trace_abort(G(L)); if (!tvisfunc(errfunc) || L->status == LUA_ERRERR) { setstrV(L, top-1, lj_err_str(L, LJ_ERR_ERRERR)); lj_err_throw(L, LUA_ERRERR); } L->status = LUA_ERRERR; copyTV(L, top, top-1); copyTV(L, top-1, errfunc); L->top = top+1; lj_vm_call(L, top, 1+1); /* Stack: |errfunc|msg| -> |msg| */ } lj_err_throw(L, LUA_ERRRUN); }
static void jit_profile_callback(lua_State *L2, lua_State *L, int samples, int vmstate) { TValue key; cTValue *tv; setlightudV(&key, (void *)&KEY_PROFILE_FUNC); tv = lj_tab_get(L, tabV(registry(L)), &key); if (tvisfunc(tv)) { char vmst = (char)vmstate; int status; setfuncV(L2, L2->top++, funcV(tv)); setthreadV(L2, L2->top++, L); setintV(L2->top++, samples); setstrV(L2, L2->top++, lj_str_new(L2, &vmst, 1)); status = lua_pcall(L2, 3, 0, 0); /* callback(thread, samples, vmstate) */ if (status) { if (G(L2)->panic) G(L2)->panic(L2); exit(EXIT_FAILURE); } lj_trace_abort(G(L2)); } }
/* Public API function: control the JIT engine. */ int luaJIT_setmode(lua_State *L, int idx, int mode) { global_State *g = G(L); int mm = mode & LUAJIT_MODE_MASK; lj_trace_abort(g); /* Abort recording on any state change. */ /* Avoid pulling the rug from under our own feet. */ if ((g->hookmask & HOOK_GC)) lj_err_caller(L, LJ_ERR_NOGCMM); switch (mm) { #if LJ_HASJIT case LUAJIT_MODE_ENGINE: if ((mode & LUAJIT_MODE_FLUSH)) { lj_trace_flushall(L); } else { if (!(mode & LUAJIT_MODE_ON)) G2J(g)->flags &= ~(uint32_t)JIT_F_ON; #if LJ_TARGET_X86ORX64 else if ((G2J(g)->flags & JIT_F_SSE2)) G2J(g)->flags |= (uint32_t)JIT_F_ON; else return 0; /* Don't turn on JIT compiler without SSE2 support. */ #else else G2J(g)->flags |= (uint32_t)JIT_F_ON; #endif lj_dispatch_update(g); } break; case LUAJIT_MODE_FUNC: case LUAJIT_MODE_ALLFUNC: case LUAJIT_MODE_ALLSUBFUNC: { cTValue *tv = idx == 0 ? frame_prev(L->base-1) : idx > 0 ? L->base + (idx-1) : L->top + idx; GCproto *pt; if ((idx == 0 || tvisfunc(tv)) && isluafunc(&gcval(tv)->fn)) pt = funcproto(&gcval(tv)->fn); /* Cannot use funcV() for frame slot. */ else if (tvisproto(tv)) pt = protoV(tv); else return 0; /* Failed. */ if (mm != LUAJIT_MODE_ALLSUBFUNC) setptmode(g, pt, mode); if (mm != LUAJIT_MODE_FUNC) setptmode_all(g, pt, mode); break; } case LUAJIT_MODE_TRACE: if (!(mode & LUAJIT_MODE_FLUSH)) return 0; /* Failed. */ lj_trace_flush(G2J(g), idx); break; #else case LUAJIT_MODE_ENGINE: case LUAJIT_MODE_FUNC: case LUAJIT_MODE_ALLFUNC: case LUAJIT_MODE_ALLSUBFUNC: UNUSED(idx); if ((mode & LUAJIT_MODE_ON)) return 0; /* Failed. */ break; #endif case LUAJIT_MODE_WRAPCFUNC: if ((mode & LUAJIT_MODE_ON)) { if (idx != 0) { cTValue *tv = idx > 0 ? L->base + (idx-1) : L->top + idx; if (tvislightud(tv)) g->wrapf = (lua_CFunction)lightudV(tv); else return 0; /* Failed. */ } else { return 0; /* Failed. */ } g->bc_cfunc_ext = BCINS_AD(BC_FUNCCW, 0, 0); } else { g->bc_cfunc_ext = BCINS_AD(BC_FUNCC, 0, 0); } break; default: return 0; /* Failed. */ }