/* Recursively set the JIT mode for all children of a prototype. */ static void setptmode_all(global_State *g, GCproto *pt, int mode) { ptrdiff_t i; for (i = -(ptrdiff_t)pt->sizekgc; i < 0; i++) { GCobj *o = gcref(pt->k.gc[i]); if (o->gch.gct == ~LJ_TPROTO) { setptmode(g, gco2pt(o), mode); setptmode_all(g, gco2pt(o), mode); } } }
/* Recursively set the JIT mode for all children of a prototype. */ static void setptmode_all(global_State *g, GCproto *pt, int mode) { ptrdiff_t i; if (!(pt->flags & PROTO_CHILD)) return; for (i = -(ptrdiff_t)pt->sizekgc; i < 0; i++) { GCobj *o = proto_kgc(pt, i); if (o->gch.gct == ~LJ_TPROTO) { setptmode(g, gco2pt(o), mode); setptmode_all(g, gco2pt(o), mode); } } }
/* 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. */ }