One Level Up
Top Level
src/lib_jit.c - luajit-2.0-src
Global variables defined
Functions defined
Macros defined
Source code
- #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"
- #define LJLIB_MODULE_jit
- static int setjitmode(lua_State *L, int mode)
- {
- int idx = 0;
- if (L->base == L->top || tvisnil(L->base)) {
- mode |= LUAJIT_MODE_ENGINE;
- } else {
-
- if (tvisfunc(L->base) || tvisproto(L->base))
- idx = 1;
- else if (!tvistrue(L->base))
- 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
- 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_FIRST, JIT_F_CPUSTRING);
- flagbits_to_strings(L, J->flags, JIT_F_OPT_FIRST, JIT_F_OPTSTRING);
- return (int)(L->top - L->base);
- #else
- setboolV(L->top++, 0);
- return 1;
- #endif
- }
- 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) {
- 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;
- } else {
- 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"
- #define LJLIB_MODULE_jit_util
- 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;
- }
- 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);
- }
- 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);
- 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");
- } else {
- GCfunc *fn = funcV(L->base);
- GCtab *t;
- lua_createtable(L, 0, 4);
- 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;
- }
- 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);
- lua_assert(op < BC__MAX);
- setintV(L->top, ins);
- setintV(L->top+1, lj_bc_mode[op]);
- L->top += 2;
- return 2;
- }
- return 0;
- }
- 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;
- }
- 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;
- }
- #if LJ_HASJIT
- 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;
- }
- static const char *const jit_trlinkname[] = {
- "none", "root", "loop", "tail-recursion", "up-recursion", "down-recursion",
- "interpreter", "return", "stitch"
- };
- LJLIB_CF(jit_util_traceinfo)
- {
- GCtrace *T = jit_checktrace(L);
- if (T) {
- GCtab *t;
- lua_createtable(L, 0, 8);
- 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");
-
- return 1;
- }
- return 0;
- }
- 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;
- }
- 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_ctsG(G(L))) {
- ptrdiff_t oldtop = savestack(L, L->top);
- luaopen_ffi(L);
- L->top = restorestack(L, oldtop);
- }
- #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;
- }
- 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;
- }
- 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;
- }
- 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) {
- 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;
- }
- LJLIB_CF(jit_util_ircalladdr)
- {
- uint32_t idx = (uint32_t)lj_lib_checkint(L, 1);
- if (idx < IRCALL__MAX) {
- setintptrV(L->top-1, (intptr_t)(void *)lj_ir_callinfo[idx].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;
- }
- #if LJ_HASJIT
- #define LJLIB_MODULE_jit_opt
- 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;
- }
- return 0;
- }
- 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_FIRST; ; 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;
- }
- lst += 1+len;
- }
- return 0;
- }
- 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;
- lua_assert(len != 0);
- 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;
- J->param[i] = n;
- if (i == JIT_P_hotloop)
- lj_dispatch_init_hotcount(J2G(J));
- return 1;
- }
- lst += 1+len;
- }
- return 0;
- }
- 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
- #if LJ_HASPROFILE
- #define LJLIB_MODULE_jit_profile
- static const char KEY_PROFILE_THREAD = 't';
- static const char KEY_PROFILE_FUNC = 'f';
- 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);
- if (status) {
- if (G(L2)->panic) G(L2)->panic(L2);
- exit(EXIT_FAILURE);
- }
- lj_trace_abort(G(L2));
- }
- }
- 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);
- TValue key;
-
- setlightudV(&key, (void *)&KEY_PROFILE_THREAD);
- setthreadV(L, lj_tab_set(L, registry, &key), L2);
- setlightudV(&key, (void *)&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;
- }
- LJLIB_CF(jit_profile_stop)
- {
- GCtab *registry;
- TValue key;
- luaJIT_profile_stop(L);
- registry = tabV(registry(L));
- setlightudV(&key, (void *)&KEY_PROFILE_THREAD);
- setnilV(lj_tab_set(L, registry, &key));
- setlightudV(&key, (void *)&KEY_PROFILE_FUNC);
- setnilV(lj_tab_set(L, registry, &key));
- lj_gc_anybarriert(L, registry);
- return 0;
- }
- 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
- #if LJ_HASJIT
- 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
- };
- #endif
- #if LJ_TARGET_ARM && LJ_TARGET_LINUX
- #include <sys/utsname.h>
- #endif
- static uint32_t jit_cpudetect(lua_State *L)
- {
- 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)) {
- #if !LJ_HASJIT
- #define JIT_F_SSE2 2
- #endif
- flags |= ((features[3] >> 26)&1) * JIT_F_SSE2;
- #if LJ_HASJIT
- flags |= ((features[2] >> 0)&1) * JIT_F_SSE3;
- flags |= ((features[2] >> 19)&1) * JIT_F_SSE4_1;
- if (vendor[2] == 0x6c65746e) {
- if ((features[0] & 0x0fff0ff0) == 0x000106c0)
- flags |= JIT_F_LEA_AGU;
- } else if (vendor[2] == 0x444d4163) {
- uint32_t fam = (features[0] & 0x0ff00f00);
- if (fam >= 0x00000f00)
- flags |= JIT_F_PREFER_IMUL;
- }
- #endif
- }
-
- #if LJ_TARGET_X86
- if (!(flags & JIT_F_SSE2))
- luaL_error(L, "CPU with SSE2 required");
- #endif
- #elif LJ_TARGET_ARM
- #if LJ_HASJIT
- int ver = LJ_ARCH_VERSION;
- #if LJ_TARGET_LINUX
- if (ver < 70) {
- struct utsname ut;
- uname(&ut);
- if (strncmp(ut.machine, "armv", 4) == 0) {
- 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;
- #endif
- #elif LJ_TARGET_ARM64
-
- #elif LJ_TARGET_PPC
- #if LJ_HASJIT
- #if LJ_ARCH_SQRT
- flags |= JIT_F_SQRT;
- #endif
- #if LJ_ARCH_ROUND
- flags |= JIT_F_ROUND;
- #endif
- #endif
- #elif LJ_TARGET_MIPS
- #if LJ_HASJIT
-
- #if LJ_ARCH_VERSION >= 20
- flags |= JIT_F_MIPS32R2;
- #endif
-
- #if defined(__GNUC__)
- if (!(flags & JIT_F_MIPS32R2)) {
- int x;
-
- __asm__("li $2, 1\n\t.long 0x00221042\n\tmove %0, $2" : "=r"(x) : : "$2");
- if (x) flags |= JIT_F_MIPS32R2;
- }
- #endif
- #endif
- #else
- #error "Missing CPU detection for this architecture"
- #endif
- UNUSED(L);
- return flags;
- }
- static void jit_init(lua_State *L)
- {
- uint32_t flags = jit_cpudetect(L);
- #if LJ_HASJIT
- jit_State *J = L2J(L);
- J->flags = flags | JIT_F_ON | JIT_F_OPT_DEFAULT;
- memcpy(J->param, jit_param_default, sizeof(J->param));
- lj_dispatch_update(G(L));
- #else
- UNUSED(flags);
- #endif
- }
- LUALIB_API int luaopen_jit(lua_State *L)
- {
- jit_init(L);
- lua_pushliteral(L, LJ_OS_NAME);
- lua_pushliteral(L, LJ_ARCH_NAME);
- lua_pushinteger(L, LUAJIT_VERSION_NUM);
- 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;
- }
One Level Up
Top Level