Mercurial
view third_party/luajit/src/lib_jit.c @ 279:b3b547563ec7
Add Google connector service and agent wiki
Implement the C/Seobeo Google Drive and Gmail connector with encrypted OAuth storage, Zenbu authentication, browser testing, AI tool discovery, chunked HTTP decoding, and Bazel coverage. Consolidate repository guidance into progressive wiki documentation and enforce arena-first allocation for new first-party C code.
Co-authored-by: Copilot <[email protected]>
Copilot-Session: 84c338fd-0939-4bb3-b7f3-1062eb213e5d
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Mon, 17 Aug 2026 22:22:36 -0700 |
| parents | 94705b5986b3 |
| children |
line wrap: on
line source
/* ** JIT library. ** Copyright (C) 2005-2023 Mike Pall. See Copyright Notice in luajit.h */ #define lib_jit_c #define LUA_LIB #include "lua.h" #include "lauxlib.h" #include "lualib.h" #include "lj_obj.h" #include "lj_gc.h" #include "lj_err.h" #include "lj_debug.h" #include "lj_str.h" #include "lj_tab.h" #include "lj_state.h" #include "lj_bc.h" #if LJ_HASFFI #include "lj_ctype.h" #endif #if LJ_HASJIT #include "lj_ir.h" #include "lj_jit.h" #include "lj_ircall.h" #include "lj_iropt.h" #include "lj_target.h" #endif #include "lj_trace.h" #include "lj_dispatch.h" #include "lj_vm.h" #include "lj_vmevent.h" #include "lj_lib.h" #include "luajit.h" /* -- jit.* functions ----------------------------------------------------- */ #define LJLIB_MODULE_jit static int setjitmode(lua_State *L, int mode) { int idx = 0; if (L->base == L->top || tvisnil(L->base)) { /* jit.on/off/flush([nil]) */ mode |= LUAJIT_MODE_ENGINE; } else { /* jit.on/off/flush(func|proto, nil|true|false) */ if (tvisfunc(L->base) || tvisproto(L->base)) idx = 1; else if (!tvistrue(L->base)) /* jit.on/off/flush(true, nil|true|false) */ goto err; if (L->base+1 < L->top && tvisbool(L->base+1)) mode |= boolV(L->base+1) ? LUAJIT_MODE_ALLFUNC : LUAJIT_MODE_ALLSUBFUNC; else mode |= LUAJIT_MODE_FUNC; } if (luaJIT_setmode(L, idx, mode) != 1) { if ((mode & LUAJIT_MODE_MASK) == LUAJIT_MODE_ENGINE) lj_err_caller(L, LJ_ERR_NOJIT); err: lj_err_argt(L, 1, LUA_TFUNCTION); } return 0; } LJLIB_CF(jit_on) { return setjitmode(L, LUAJIT_MODE_ON); } LJLIB_CF(jit_off) { return setjitmode(L, LUAJIT_MODE_OFF); } LJLIB_CF(jit_flush) { #if LJ_HASJIT if (L->base < L->top && tvisnumber(L->base)) { int traceno = lj_lib_checkint(L, 1); luaJIT_setmode(L, traceno, LUAJIT_MODE_FLUSH|LUAJIT_MODE_TRACE); return 0; } #endif return setjitmode(L, LUAJIT_MODE_FLUSH); } #if LJ_HASJIT /* Push a string for every flag bit that is set. */ static void flagbits_to_strings(lua_State *L, uint32_t flags, uint32_t base, const char *str) { for (; *str; base <<= 1, str += 1+*str) if (flags & base) setstrV(L, L->top++, lj_str_new(L, str+1, *(uint8_t *)str)); } #endif LJLIB_CF(jit_status) { #if LJ_HASJIT jit_State *J = L2J(L); L->top = L->base; setboolV(L->top++, (J->flags & JIT_F_ON) ? 1 : 0); flagbits_to_strings(L, J->flags, JIT_F_CPU, JIT_F_CPUSTRING); flagbits_to_strings(L, J->flags, JIT_F_OPT, JIT_F_OPTSTRING); return (int)(L->top - L->base); #else setboolV(L->top++, 0); return 1; #endif } LJLIB_CF(jit_security) { int idx = lj_lib_checkopt(L, 1, -1, LJ_SECURITY_MODESTRING); setintV(L->top++, ((LJ_SECURITY_MODE >> (2*idx)) & 3)); return 1; } LJLIB_CF(jit_attach) { #ifdef LUAJIT_DISABLE_VMEVENT luaL_error(L, "vmevent API disabled"); #else GCfunc *fn = lj_lib_checkfunc(L, 1); GCstr *s = lj_lib_optstr(L, 2); luaL_findtable(L, LUA_REGISTRYINDEX, LJ_VMEVENTS_REGKEY, LJ_VMEVENTS_HSIZE); if (s) { /* Attach to given event. */ const uint8_t *p = (const uint8_t *)strdata(s); uint32_t h = s->len; while (*p) h = h ^ (lj_rol(h, 6) + *p++); lua_pushvalue(L, 1); lua_rawseti(L, -2, VMEVENT_HASHIDX(h)); G(L)->vmevmask = VMEVENT_NOCACHE; /* Invalidate cache. */ } else { /* Detach if no event given. */ setnilV(L->top++); while (lua_next(L, -2)) { L->top--; if (tvisfunc(L->top) && funcV(L->top) == fn) { setnilV(lj_tab_set(L, tabV(L->top-2), L->top-1)); } } } #endif return 0; } LJLIB_PUSH(top-5) LJLIB_SET(os) LJLIB_PUSH(top-4) LJLIB_SET(arch) LJLIB_PUSH(top-3) LJLIB_SET(version_num) LJLIB_PUSH(top-2) LJLIB_SET(version) #include "lj_libdef.h" /* -- jit.util.* functions ------------------------------------------------ */ #define LJLIB_MODULE_jit_util /* -- Reflection API for Lua functions ------------------------------------ */ /* Return prototype of first argument (Lua function or prototype object) */ static GCproto *check_Lproto(lua_State *L, int nolua) { TValue *o = L->base; if (L->top > o) { if (tvisproto(o)) { return protoV(o); } else if (tvisfunc(o)) { if (isluafunc(funcV(o))) return funcproto(funcV(o)); else if (nolua) return NULL; } } lj_err_argt(L, 1, LUA_TFUNCTION); return NULL; /* unreachable */ } static void setintfield(lua_State *L, GCtab *t, const char *name, int32_t val) { setintV(lj_tab_setstr(L, t, lj_str_newz(L, name)), val); } /* local info = jit.util.funcinfo(func [,pc]) */ LJLIB_CF(jit_util_funcinfo) { GCproto *pt = check_Lproto(L, 1); if (pt) { BCPos pc = (BCPos)lj_lib_optint(L, 2, 0); GCtab *t; lua_createtable(L, 0, 16); /* Increment hash size if fields are added. */ t = tabV(L->top-1); setintfield(L, t, "linedefined", pt->firstline); setintfield(L, t, "lastlinedefined", pt->firstline + pt->numline); setintfield(L, t, "stackslots", pt->framesize); setintfield(L, t, "params", pt->numparams); setintfield(L, t, "bytecodes", (int32_t)pt->sizebc); setintfield(L, t, "gcconsts", (int32_t)pt->sizekgc); setintfield(L, t, "nconsts", (int32_t)pt->sizekn); setintfield(L, t, "upvalues", (int32_t)pt->sizeuv); if (pc < pt->sizebc) setintfield(L, t, "currentline", lj_debug_line(pt, pc)); lua_pushboolean(L, (pt->flags & PROTO_VARARG)); lua_setfield(L, -2, "isvararg"); lua_pushboolean(L, (pt->flags & PROTO_CHILD)); lua_setfield(L, -2, "children"); setstrV(L, L->top++, proto_chunkname(pt)); lua_setfield(L, -2, "source"); lj_debug_pushloc(L, pt, pc); lua_setfield(L, -2, "loc"); setprotoV(L, lj_tab_setstr(L, t, lj_str_newlit(L, "proto")), pt); } else { GCfunc *fn = funcV(L->base); GCtab *t; lua_createtable(L, 0, 4); /* Increment hash size if fields are added. */ t = tabV(L->top-1); if (!iscfunc(fn)) setintfield(L, t, "ffid", fn->c.ffid); setintptrV(lj_tab_setstr(L, t, lj_str_newlit(L, "addr")), (intptr_t)(void *)fn->c.f); setintfield(L, t, "upvalues", fn->c.nupvalues); } return 1; } /* local ins, m = jit.util.funcbc(func, pc) */ LJLIB_CF(jit_util_funcbc) { GCproto *pt = check_Lproto(L, 0); BCPos pc = (BCPos)lj_lib_checkint(L, 2); if (pc < pt->sizebc) { BCIns ins = proto_bc(pt)[pc]; BCOp op = bc_op(ins); lj_assertL(op < BC__MAX, "bad bytecode op %d", op); setintV(L->top, ins); setintV(L->top+1, lj_bc_mode[op]); L->top += 2; return 2; } return 0; } /* local k = jit.util.funck(func, idx) */ LJLIB_CF(jit_util_funck) { GCproto *pt = check_Lproto(L, 0); ptrdiff_t idx = (ptrdiff_t)lj_lib_checkint(L, 2); if (idx >= 0) { if (idx < (ptrdiff_t)pt->sizekn) { copyTV(L, L->top-1, proto_knumtv(pt, idx)); return 1; } } else { if (~idx < (ptrdiff_t)pt->sizekgc) { GCobj *gc = proto_kgc(pt, idx); setgcV(L, L->top-1, gc, ~gc->gch.gct); return 1; } } return 0; } /* local name = jit.util.funcuvname(func, idx) */ LJLIB_CF(jit_util_funcuvname) { GCproto *pt = check_Lproto(L, 0); uint32_t idx = (uint32_t)lj_lib_checkint(L, 2); if (idx < pt->sizeuv) { setstrV(L, L->top-1, lj_str_newz(L, lj_debug_uvname(pt, idx))); return 1; } return 0; } /* -- Reflection API for traces ------------------------------------------- */ #if LJ_HASJIT /* Check trace argument. Must not throw for non-existent trace numbers. */ static GCtrace *jit_checktrace(lua_State *L) { TraceNo tr = (TraceNo)lj_lib_checkint(L, 1); jit_State *J = L2J(L); if (tr > 0 && tr < J->sizetrace) return traceref(J, tr); return NULL; } /* Names of link types. ORDER LJ_TRLINK */ static const char *const jit_trlinkname[] = { "none", "root", "loop", "tail-recursion", "up-recursion", "down-recursion", "interpreter", "return", "stitch" }; /* local info = jit.util.traceinfo(tr) */ LJLIB_CF(jit_util_traceinfo) { GCtrace *T = jit_checktrace(L); if (T) { GCtab *t; 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); setstrV(L, L->top++, lj_str_newz(L, jit_trlinkname[T->linktype])); lua_setfield(L, -2, "linktype"); /* There are many more fields. Add them only when needed. */ return 1; } return 0; } /* local m, ot, op1, op2, prev = jit.util.traceir(tr, idx) */ LJLIB_CF(jit_util_traceir) { GCtrace *T = jit_checktrace(L); IRRef ref = (IRRef)lj_lib_checkint(L, 2) + REF_BIAS; if (T && ref >= REF_BIAS && ref < T->nins) { IRIns *ir = &T->ir[ref]; int32_t m = lj_ir_mode[ir->o]; setintV(L->top-2, m); setintV(L->top-1, ir->ot); setintV(L->top++, (int32_t)ir->op1 - (irm_op1(m)==IRMref ? REF_BIAS : 0)); setintV(L->top++, (int32_t)ir->op2 - (irm_op2(m)==IRMref ? REF_BIAS : 0)); setintV(L->top++, ir->prev); return 5; } return 0; } /* local k, t [, slot] = jit.util.tracek(tr, idx) */ LJLIB_CF(jit_util_tracek) { GCtrace *T = jit_checktrace(L); IRRef ref = (IRRef)lj_lib_checkint(L, 2) + REF_BIAS; if (T && ref >= T->nk && ref < REF_BIAS) { IRIns *ir = &T->ir[ref]; int32_t slot = -1; if (ir->o == IR_KSLOT) { slot = ir->op2; ir = &T->ir[ir->op1]; } #if LJ_HASFFI if (ir->o == IR_KINT64) ctype_loadffi(L); #endif lj_ir_kvalue(L, L->top-2, ir); setintV(L->top-1, (int32_t)irt_type(ir->t)); if (slot == -1) return 2; setintV(L->top++, slot); return 3; } return 0; } /* local snap = jit.util.tracesnap(tr, sn) */ LJLIB_CF(jit_util_tracesnap) { GCtrace *T = jit_checktrace(L); SnapNo sn = (SnapNo)lj_lib_checkint(L, 2); if (T && sn < T->nsnap) { SnapShot *snap = &T->snap[sn]; SnapEntry *map = &T->snapmap[snap->mapofs]; MSize n, nent = snap->nent; GCtab *t; lua_createtable(L, nent+2, 0); t = tabV(L->top-1); setintV(lj_tab_setint(L, t, 0), (int32_t)snap->ref - REF_BIAS); setintV(lj_tab_setint(L, t, 1), (int32_t)snap->nslots); for (n = 0; n < nent; n++) setintV(lj_tab_setint(L, t, (int32_t)(n+2)), (int32_t)map[n]); setintV(lj_tab_setint(L, t, (int32_t)(nent+2)), (int32_t)SNAP(255, 0, 0)); return 1; } return 0; } /* local mcode, addr, loop = jit.util.tracemc(tr) */ LJLIB_CF(jit_util_tracemc) { GCtrace *T = jit_checktrace(L); if (T && T->mcode != NULL) { setstrV(L, L->top-1, lj_str_new(L, (const char *)T->mcode, T->szmcode)); setintptrV(L->top++, (intptr_t)(void *)T->mcode); setintV(L->top++, T->mcloop); return 3; } return 0; } /* local addr = jit.util.traceexitstub([tr,] exitno) */ LJLIB_CF(jit_util_traceexitstub) { #ifdef EXITSTUBS_PER_GROUP ExitNo exitno = (ExitNo)lj_lib_checkint(L, 1); jit_State *J = L2J(L); if (exitno < EXITSTUBS_PER_GROUP*LJ_MAX_EXITSTUBGR) { setintptrV(L->top-1, (intptr_t)(void *)exitstub_addr(J, exitno)); return 1; } #else if (L->top > L->base+1) { /* Don't throw for one-argument variant. */ GCtrace *T = jit_checktrace(L); ExitNo exitno = (ExitNo)lj_lib_checkint(L, 2); ExitNo maxexit = T->root ? T->nsnap+1 : T->nsnap; if (T && T->mcode != NULL && exitno < maxexit) { setintptrV(L->top-1, (intptr_t)(void *)exitstub_trace_addr(T, exitno)); return 1; } } #endif return 0; } /* local addr = jit.util.ircalladdr(idx) */ LJLIB_CF(jit_util_ircalladdr) { uint32_t idx = (uint32_t)lj_lib_checkint(L, 1); if (idx < IRCALL__MAX) { ASMFunction func = lj_ir_callinfo[idx].func; setintptrV(L->top-1, (intptr_t)(void *)lj_ptr_strip(func)); return 1; } return 0; } #endif #include "lj_libdef.h" static int luaopen_jit_util(lua_State *L) { LJ_LIB_REG(L, NULL, jit_util); return 1; } /* -- jit.opt module ------------------------------------------------------ */ #if LJ_HASJIT #define LJLIB_MODULE_jit_opt /* Parse optimization level. */ static int jitopt_level(jit_State *J, const char *str) { if (str[0] >= '0' && str[0] <= '9' && str[1] == '\0') { uint32_t flags; if (str[0] == '0') flags = JIT_F_OPT_0; else if (str[0] == '1') flags = JIT_F_OPT_1; else if (str[0] == '2') flags = JIT_F_OPT_2; else flags = JIT_F_OPT_3; J->flags = (J->flags & ~JIT_F_OPT_MASK) | flags; return 1; /* Ok. */ } return 0; /* No match. */ } /* Parse optimization flag. */ static int jitopt_flag(jit_State *J, const char *str) { const char *lst = JIT_F_OPTSTRING; uint32_t opt; int set = 1; if (str[0] == '+') { str++; } else if (str[0] == '-') { str++; set = 0; } else if (str[0] == 'n' && str[1] == 'o') { str += str[2] == '-' ? 3 : 2; set = 0; } for (opt = JIT_F_OPT; ; opt <<= 1) { size_t len = *(const uint8_t *)lst; if (len == 0) break; if (strncmp(str, lst+1, len) == 0 && str[len] == '\0') { if (set) J->flags |= opt; else J->flags &= ~opt; return 1; /* Ok. */ } lst += 1+len; } return 0; /* No match. */ } /* Parse optimization parameter. */ static int jitopt_param(jit_State *J, const char *str) { const char *lst = JIT_P_STRING; int i; for (i = 0; i < JIT_P__MAX; i++) { size_t len = *(const uint8_t *)lst; lj_assertJ(len != 0, "bad JIT_P_STRING"); if (strncmp(str, lst+1, len) == 0 && str[len] == '=') { int32_t n = 0; const char *p = &str[len+1]; while (*p >= '0' && *p <= '9') n = n*10 + (*p++ - '0'); if (*p) return 0; /* Malformed number. */ J->param[i] = n; if (i == JIT_P_hotloop) lj_dispatch_init_hotcount(J2G(J)); return 1; /* Ok. */ } lst += 1+len; } return 0; /* No match. */ } /* jit.opt.start(flags...) */ LJLIB_CF(jit_opt_start) { jit_State *J = L2J(L); int nargs = (int)(L->top - L->base); if (nargs == 0) { J->flags = (J->flags & ~JIT_F_OPT_MASK) | JIT_F_OPT_DEFAULT; } else { int i; for (i = 1; i <= nargs; i++) { const char *str = strdata(lj_lib_checkstr(L, i)); if (!jitopt_level(J, str) && !jitopt_flag(J, str) && !jitopt_param(J, str)) lj_err_callerv(L, LJ_ERR_JITOPT, str); } } return 0; } #include "lj_libdef.h" #endif /* -- jit.profile module -------------------------------------------------- */ #if LJ_HASPROFILE #define LJLIB_MODULE_jit_profile /* Not loaded by default, use: local profile = require("jit.profile") */ #define KEY_PROFILE_THREAD (U64x(80000000,00000000)|'t') #define KEY_PROFILE_FUNC (U64x(80000000,00000000)|'f') static void jit_profile_callback(lua_State *L2, lua_State *L, int samples, int vmstate) { TValue key; cTValue *tv; key.u64 = 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)); } } /* profile.start(mode, cb) */ LJLIB_CF(jit_profile_start) { GCtab *registry = tabV(registry(L)); GCstr *mode = lj_lib_optstr(L, 1); GCfunc *func = lj_lib_checkfunc(L, 2); lua_State *L2 = lua_newthread(L); /* Thread that runs profiler callback. */ TValue key; /* Anchor thread and function in registry. */ key.u64 = KEY_PROFILE_THREAD; setthreadV(L, lj_tab_set(L, registry, &key), L2); key.u64 = KEY_PROFILE_FUNC; setfuncV(L, lj_tab_set(L, registry, &key), func); lj_gc_anybarriert(L, registry); luaJIT_profile_start(L, mode ? strdata(mode) : "", (luaJIT_profile_callback)jit_profile_callback, L2); return 0; } /* profile.stop() */ LJLIB_CF(jit_profile_stop) { GCtab *registry; TValue key; luaJIT_profile_stop(L); registry = tabV(registry(L)); key.u64 = KEY_PROFILE_THREAD; setnilV(lj_tab_set(L, registry, &key)); key.u64 = KEY_PROFILE_FUNC; setnilV(lj_tab_set(L, registry, &key)); lj_gc_anybarriert(L, registry); return 0; } /* dump = profile.dumpstack([thread,] fmt, depth) */ LJLIB_CF(jit_profile_dumpstack) { lua_State *L2 = L; int arg = 0; size_t len; int depth; GCstr *fmt; const char *p; if (L->top > L->base && tvisthread(L->base)) { L2 = threadV(L->base); arg = 1; } fmt = lj_lib_checkstr(L, arg+1); depth = lj_lib_checkint(L, arg+2); p = luaJIT_profile_dumpstack(L2, strdata(fmt), depth, &len); lua_pushlstring(L, p, len); return 1; } #include "lj_libdef.h" static int luaopen_jit_profile(lua_State *L) { LJ_LIB_REG(L, NULL, jit_profile); return 1; } #endif /* -- JIT compiler initialization ----------------------------------------- */ #if LJ_HASJIT /* Default values for JIT parameters. */ static const int32_t jit_param_default[JIT_P__MAX+1] = { #define JIT_PARAMINIT(len, name, value) (value), JIT_PARAMDEF(JIT_PARAMINIT) #undef JIT_PARAMINIT 0 }; #if LJ_TARGET_ARM && LJ_TARGET_LINUX #include <sys/utsname.h> #endif /* Arch-dependent CPU feature detection. */ static uint32_t jit_cpudetect(void) { uint32_t flags = 0; #if LJ_TARGET_X86ORX64 uint32_t vendor[4]; uint32_t features[4]; if (lj_vm_cpuid(0, vendor) && lj_vm_cpuid(1, features)) { flags |= ((features[2] >> 0)&1) * JIT_F_SSE3; flags |= ((features[2] >> 19)&1) * JIT_F_SSE4_1; if (vendor[0] >= 7) { uint32_t xfeatures[4]; lj_vm_cpuid(7, xfeatures); flags |= ((xfeatures[1] >> 8)&1) * JIT_F_BMI2; } } /* Don't bother checking for SSE2 -- the VM will crash before getting here. */ #elif LJ_TARGET_ARM int ver = LJ_ARCH_VERSION; /* Compile-time ARM CPU detection. */ #if LJ_TARGET_LINUX if (ver < 70) { /* Runtime ARM CPU detection. */ struct utsname ut; uname(&ut); if (strncmp(ut.machine, "armv", 4) == 0) { if (ut.machine[4] >= '8') ver = 80; else if (ut.machine[4] == '7') ver = 70; else if (ut.machine[4] == '6') ver = 60; } } #endif flags |= ver >= 70 ? JIT_F_ARMV7 : ver >= 61 ? JIT_F_ARMV6T2_ : ver >= 60 ? JIT_F_ARMV6_ : 0; flags |= LJ_ARCH_HASFPU == 0 ? 0 : ver >= 70 ? JIT_F_VFPV3 : JIT_F_VFPV2; #elif LJ_TARGET_ARM64 /* No optional CPU features to detect (for now). */ #elif LJ_TARGET_PPC #if LJ_ARCH_SQRT flags |= JIT_F_SQRT; #endif #if LJ_ARCH_ROUND flags |= JIT_F_ROUND; #endif #elif LJ_TARGET_MIPS /* Compile-time MIPS CPU detection. */ #if LJ_ARCH_VERSION >= 20 flags |= JIT_F_MIPSXXR2; #endif /* Runtime MIPS CPU detection. */ #if defined(__GNUC__) if (!(flags & JIT_F_MIPSXXR2)) { int x; #ifdef __mips16 x = 0; /* Runtime detection is difficult. Ensure optimal -march flags. */ #else /* On MIPS32R1 rotr is treated as srl. rotr r2,r2,1 -> srl r2,r2,1. */ __asm__("li $2, 1\n\t.long 0x00221042\n\tmove %0, $2" : "=r"(x) : : "$2"); #endif if (x) flags |= JIT_F_MIPSXXR2; /* Either 0x80000000 (R2) or 0 (R1). */ } #endif #else #error "Missing CPU detection for this architecture" #endif return flags; } /* Initialize JIT compiler. */ static void jit_init(lua_State *L) { jit_State *J = L2J(L); J->flags = jit_cpudetect() | JIT_F_ON | JIT_F_OPT_DEFAULT; memcpy(J->param, jit_param_default, sizeof(J->param)); lj_dispatch_update(G(L)); } #endif LUALIB_API int luaopen_jit(lua_State *L) { #if LJ_HASJIT jit_init(L); #endif lua_pushliteral(L, LJ_OS_NAME); lua_pushliteral(L, LJ_ARCH_NAME); lua_pushinteger(L, LUAJIT_VERSION_NUM); /* Deprecated. */ lua_pushliteral(L, LUAJIT_VERSION); LJ_LIB_REG(L, LUA_JITLIBNAME, jit); #if LJ_HASPROFILE lj_lib_prereg(L, LUA_JITLIBNAME ".profile", luaopen_jit_profile, tabref(L->env)); #endif #ifndef LUAJIT_DISABLE_JITUTIL lj_lib_prereg(L, LUA_JITLIBNAME ".util", luaopen_jit_util, tabref(L->env)); #endif #if LJ_HASJIT LJ_LIB_REG(L, "jit.opt", jit_opt); #endif L->top -= 2; return 1; }