ljx

FORK: LuaJIT with native 5.2 and 5.3 support
git clone https://git.neptards.moe/neptards/ljx.git
Log | Files | Refs | README

lib_jit.c (20777B)


      1 /*
      2 ** JIT library.
      3 ** Copyright (C) 2005-2016 Mike Pall. See Copyright Notice in luajit.h
      4 */
      5 
      6 #define lib_jit_c
      7 #define LUA_LIB
      8 
      9 #include "lua.h"
     10 #include "lauxlib.h"
     11 #include "lualib.h"
     12 
     13 #include "lj_obj.h"
     14 #include "lj_gc.h"
     15 #include "lj_err.h"
     16 #include "lj_debug.h"
     17 #include "lj_str.h"
     18 #include "lj_tab.h"
     19 #include "lj_state.h"
     20 #include "lj_bc.h"
     21 #if LJ_HASFFI
     22 #include "lj_ctype.h"
     23 #endif
     24 #if LJ_HASJIT
     25 #include "lj_ir.h"
     26 #include "lj_jit.h"
     27 #include "lj_ircall.h"
     28 #include "lj_iropt.h"
     29 #include "lj_target.h"
     30 #endif
     31 #include "lj_trace.h"
     32 #include "lj_dispatch.h"
     33 #include "lj_vm.h"
     34 #include "lj_vmevent.h"
     35 #include "lj_lib.h"
     36 
     37 #include "luajit.h"
     38 
     39 /* -- jit.* functions ----------------------------------------------------- */
     40 
     41 #define LJLIB_MODULE_jit
     42 
     43 static int setjitmode(lua_State *L, int mode)
     44 {
     45   int idx = 0;
     46   if (L->base == L->top || tvisnil(L->base)) {  /* jit.on/off/flush([nil]) */
     47     mode |= LUAJIT_MODE_ENGINE;
     48   } else {
     49     /* jit.on/off/flush(func|proto, nil|true|false) */
     50     if (tvisfunc(L->base) || tvisproto(L->base))
     51       idx = 1;
     52     else if (!tvistrue(L->base))  /* jit.on/off/flush(true, nil|true|false) */
     53       goto err;
     54     if (L->base+1 < L->top && tvisbool(L->base+1))
     55       mode |= boolV(L->base+1) ? LUAJIT_MODE_ALLFUNC : LUAJIT_MODE_ALLSUBFUNC;
     56     else
     57       mode |= LUAJIT_MODE_FUNC;
     58   }
     59   if (luaJIT_setmode(L, idx, mode) != 1) {
     60     if ((mode & LUAJIT_MODE_MASK) == LUAJIT_MODE_ENGINE)
     61       lj_err_caller(L, LJ_ERR_NOJIT);
     62   err:
     63     lj_err_argt(L, 1, LUA_TFUNCTION);
     64   }
     65   return 0;
     66 }
     67 
     68 LJLIB_CF(jit_on)
     69 {
     70   return setjitmode(L, LUAJIT_MODE_ON);
     71 }
     72 
     73 LJLIB_CF(jit_off)
     74 {
     75   return setjitmode(L, LUAJIT_MODE_OFF);
     76 }
     77 
     78 LJLIB_CF(jit_flush)
     79 {
     80 #if LJ_HASJIT
     81   if (L->base < L->top && tvisnumber(L->base)) {
     82     int traceno = lj_lib_checkint(L, 1);
     83     luaJIT_setmode(L, traceno, LUAJIT_MODE_FLUSH|LUAJIT_MODE_TRACE);
     84     return 0;
     85   }
     86 #endif
     87   return setjitmode(L, LUAJIT_MODE_FLUSH);
     88 }
     89 
     90 #if LJ_HASJIT
     91 /* Push a string for every flag bit that is set. */
     92 static void flagbits_to_strings(lua_State *L, uint32_t flags, uint32_t base,
     93 				const char *str)
     94 {
     95   for (; *str; base <<= 1, str += 1+*str)
     96     if (flags & base)
     97       setstrV(L, L->top++, lj_str_new(L, str+1, *(uint8_t *)str));
     98 }
     99 #endif
    100 
    101 LJLIB_CF(jit_status)
    102 {
    103 #if LJ_HASJIT
    104   jit_State *J = L2J(L);
    105   L->top = L->base;
    106   setboolV(L->top++, (J->flags & JIT_F_ON) ? 1 : 0);
    107   flagbits_to_strings(L, J->flags, JIT_F_CPU_FIRST, JIT_F_CPUSTRING);
    108   flagbits_to_strings(L, J->flags, JIT_F_OPT_FIRST, JIT_F_OPTSTRING);
    109   return (int)(L->top - L->base);
    110 #else
    111   setboolV(L->top++, 0);
    112   return 1;
    113 #endif
    114 }
    115 
    116 LJLIB_CF(jit_attach)
    117 {
    118 #ifdef LUAJIT_DISABLE_VMEVENT
    119   luaL_error(L, "vmevent API disabled");
    120 #else
    121   GCfunc *fn = lj_lib_checkfunc(L, 1);
    122   GCstr *s = lj_lib_optstr(L, 2);
    123   luaL_findtable(L, LUA_REGISTRYINDEX, LJ_VMEVENTS_REGKEY, LJ_VMEVENTS_HSIZE);
    124   if (s) {  /* Attach to given event. */
    125     const uint8_t *p = (const uint8_t *)strdata(s);
    126     uint32_t h = s->len;
    127     while (*p) h = h ^ (lj_rol(h, 6) + *p++);
    128     lua_pushvalue(L, 1);
    129     lua_rawseti(L, -2, VMEVENT_HASHIDX(h));
    130     G(L)->vmevmask = VMEVENT_NOCACHE;  /* Invalidate cache. */
    131   } else {  /* Detach if no event given. */
    132     setnilV(L->top++);
    133     while (lua_next(L, -2)) {
    134       L->top--;
    135       if (tvisfunc(L->top) && funcV(L->top) == fn) {
    136 	setnilV(lj_tab_set(L, tabV(L->top-2), L->top-1));
    137       }
    138     }
    139   }
    140 #endif
    141   return 0;
    142 }
    143 
    144 LJLIB_PUSH(top-5) LJLIB_SET(os)
    145 LJLIB_PUSH(top-4) LJLIB_SET(arch)
    146 LJLIB_PUSH(top-3) LJLIB_SET(version_num)
    147 LJLIB_PUSH(top-2) LJLIB_SET(version)
    148 
    149 #include "lj_libdef.h"
    150 
    151 /* -- jit.util.* functions ------------------------------------------------ */
    152 
    153 #define LJLIB_MODULE_jit_util
    154 
    155 /* -- Reflection API for Lua functions ------------------------------------ */
    156 
    157 /* Return prototype of first argument (Lua function or prototype object) */
    158 static GCproto *check_Lproto(lua_State *L, int nolua)
    159 {
    160   TValue *o = L->base;
    161   if (L->top > o) {
    162     if (tvisproto(o)) {
    163       return protoV(o);
    164     } else if (tvisfunc(o)) {
    165       if (isluafunc(funcV(o)))
    166 	return funcproto(funcV(o));
    167       else if (nolua)
    168 	return NULL;
    169     }
    170   }
    171   lj_err_argt(L, 1, LUA_TFUNCTION);
    172   return NULL;  /* unreachable */
    173 }
    174 
    175 static void setintfield(lua_State *L, GCtab *t, const char *name, int32_t val)
    176 {
    177   setintV(lj_tab_setstr(L, t, lj_str_newz(L, name)), val);
    178 }
    179 
    180 /* local info = jit.util.funcinfo(func [,pc]) */
    181 LJLIB_CF(jit_util_funcinfo)
    182 {
    183   GCproto *pt = check_Lproto(L, 1);
    184   if (pt) {
    185     BCPos pc = (BCPos)lj_lib_optint(L, 2, 0);
    186     GCtab *t;
    187     int i;
    188     lua_createtable(L, 0, 17);  /* Increment hash size if fields are added. */
    189     t = tabV(L->top-1);
    190     setintfield(L, t, "linedefined", pt->firstline);
    191     setintfield(L, t, "lastlinedefined", pt->firstline + pt->numline);
    192     setintfield(L, t, "stackslots", pt->framesize);
    193     setintfield(L, t, "params", pt->numparams);
    194     setintfield(L, t, "bytecodes", (int32_t)pt->sizebc);
    195     setintfield(L, t, "gcconsts", (int32_t)pt->sizekgc);
    196     setintfield(L, t, "nconsts", (int32_t)pt->sizekn);
    197     setintfield(L, t, "upvalues", (int32_t)pt->sizeuv);
    198     if (pc < pt->sizebc)
    199       setintfield(L, t, "currentline", lj_debug_line(pt, pc));
    200     lua_pushboolean(L, (pt->flags & PROTO_VARARG));
    201     lua_setfield(L, -2, "isvararg");
    202     lua_pushboolean(L, (pt->flags & PROTO_CHILD));
    203     lua_setfield(L, -2, "children");
    204     setstrV(L, L->top++, proto_chunkname(pt));
    205     lua_setfield(L, -2, "source");
    206     lj_debug_pushloc(L, pt, pc);
    207     lua_setfield(L, -2, "loc");
    208     /* UV prototype fields. TBD: ditto for consts? */
    209     lua_createtable(L, pt->sizeuv+1, 0);
    210     for (i = 0; i < pt->sizeuv; i++)
    211       setintV(lj_tab_setint(L, tabV(L->top-1), i+1), proto_uv(pt)[i]);
    212     lua_setfield(L, -2, "uvinit");
    213   } else {
    214     GCfunc *fn = funcV(L->base);
    215     GCtab *t;
    216     lua_createtable(L, 0, 4);  /* Increment hash size if fields are added. */
    217     t = tabV(L->top-1);
    218     if (!iscfunc(fn))
    219       setintfield(L, t, "ffid", fn->c.ffid);
    220     setintptrV(lj_tab_setstr(L, t, lj_str_newlit(L, "addr")),
    221 	       (intptr_t)(void *)fn->c.f);
    222     setintfield(L, t, "upvalues", fn->c.nupvalues);
    223   }
    224   return 1;
    225 }
    226 
    227 /* local ins, m = jit.util.funcbc(func, pc) */
    228 LJLIB_CF(jit_util_funcbc)
    229 {
    230   GCproto *pt = check_Lproto(L, 0);
    231   BCPos pc = (BCPos)lj_lib_checkint(L, 2);
    232   if (pc < pt->sizebc) {
    233     BCIns ins = proto_bc(pt)[pc];
    234     BCOp op = bc_op(ins);
    235     lua_assert(op < BC__MAX);
    236     setintV(L->top, ins);
    237     setintV(L->top+1, lj_bc_mode[op]);
    238     L->top += 2;
    239     return 2;
    240   }
    241   return 0;
    242 }
    243 
    244 /* local k = jit.util.funck(func, idx) */
    245 LJLIB_CF(jit_util_funck)
    246 {
    247   GCproto *pt = check_Lproto(L, 0);
    248   ptrdiff_t idx = (ptrdiff_t)lj_lib_checkint(L, 2);
    249   if (idx >= 0) {
    250     if (idx < (ptrdiff_t)pt->sizekn) {
    251       copyTV(L, L->top-1, proto_knumtv(pt, idx));
    252       return 1;
    253     }
    254   } else {
    255     if (~idx < (ptrdiff_t)pt->sizekgc) {
    256       GCobj *gc = proto_kgc(pt, idx);
    257       setgcV(L, L->top-1, gc, ~gc->gch.gct);
    258       return 1;
    259     }
    260   }
    261   return 0;
    262 }
    263 
    264 /* local name = jit.util.funcuvname(func, idx) */
    265 LJLIB_CF(jit_util_funcuvname)
    266 {
    267   GCproto *pt = check_Lproto(L, 0);
    268   uint32_t idx = (uint32_t)lj_lib_checkint(L, 2);
    269   if (idx < pt->sizeuv) {
    270     setstrV(L, L->top-1, lj_str_newz(L, lj_debug_uvname(pt, idx)));
    271     return 1;
    272   }
    273   return 0;
    274 }
    275 
    276 /* -- Reflection API for traces ------------------------------------------- */
    277 
    278 #if LJ_HASJIT
    279 
    280 /* Check trace argument. Must not throw for non-existent trace numbers. */
    281 static GCtrace *jit_checktrace(lua_State *L)
    282 {
    283   TraceNo tr = (TraceNo)lj_lib_checkint(L, 1);
    284   jit_State *J = L2J(L);
    285   if (tr > 0 && tr < J->sizetrace)
    286     return traceref(J, tr);
    287   return NULL;
    288 }
    289 
    290 /* Names of link types. ORDER LJ_TRLINK */
    291 static const char *const jit_trlinkname[] = {
    292   "none", "root", "loop", "tail-recursion", "up-recursion", "down-recursion",
    293   "interpreter", "return", "stitch"
    294 };
    295 
    296 /* local info = jit.util.traceinfo(tr) */
    297 LJLIB_CF(jit_util_traceinfo)
    298 {
    299   GCtrace *T = jit_checktrace(L);
    300   if (T) {
    301     GCtab *t;
    302     lua_createtable(L, 0, 8);  /* Increment hash size if fields are added. */
    303     t = tabV(L->top-1);
    304     setintfield(L, t, "nins", (int32_t)T->nins - REF_BIAS - 1);
    305     setintfield(L, t, "nk", REF_BIAS - (int32_t)T->nk);
    306     setintfield(L, t, "link", T->link);
    307     setintfield(L, t, "nexit", T->nsnap);
    308     setstrV(L, L->top++, lj_str_newz(L, jit_trlinkname[T->linktype]));
    309     lua_setfield(L, -2, "linktype");
    310     /* There are many more fields. Add them only when needed. */
    311     return 1;
    312   }
    313   return 0;
    314 }
    315 
    316 /* local m, ot, op1, op2, prev = jit.util.traceir(tr, idx) */
    317 LJLIB_CF(jit_util_traceir)
    318 {
    319   GCtrace *T = jit_checktrace(L);
    320   IRRef ref = (IRRef)lj_lib_checkint(L, 2) + REF_BIAS;
    321   if (T && ref >= REF_BIAS && ref < T->nins) {
    322     IRIns *ir = &T->ir[ref];
    323     int32_t m = lj_ir_mode[ir->o];
    324     setintV(L->top-2, m);
    325     setintV(L->top-1, ir->ot);
    326     setintV(L->top++, (int32_t)ir->op1 - (irm_op1(m)==IRMref ? REF_BIAS : 0));
    327     setintV(L->top++, (int32_t)ir->op2 - (irm_op2(m)==IRMref ? REF_BIAS : 0));
    328     setintV(L->top++, ir->prev);
    329     return 5;
    330   }
    331   return 0;
    332 }
    333 
    334 /* local k, t [, slot] = jit.util.tracek(tr, idx) */
    335 LJLIB_CF(jit_util_tracek)
    336 {
    337   GCtrace *T = jit_checktrace(L);
    338   IRRef ref = (IRRef)lj_lib_checkint(L, 2) + REF_BIAS;
    339   if (T && ref >= T->nk && ref < REF_BIAS) {
    340     IRIns *ir = &T->ir[ref];
    341     int32_t slot = -1;
    342     if (ir->o == IR_KSLOT) {
    343       slot = ir->op2;
    344       ir = &T->ir[ir->op1];
    345     }
    346 #if LJ_HASFFI
    347     if (ir->o == IR_KINT64 && !ctype_ctsG(G(L))) {
    348       ptrdiff_t oldtop = savestack(L, L->top);
    349       luaopen_ffi(L);  /* Load FFI library on-demand. */
    350       L->top = restorestack(L, oldtop);
    351     }
    352 #endif
    353     lj_ir_kvalue(L, L->top-2, ir);
    354     setintV(L->top-1, (int32_t)irt_type(ir->t));
    355     if (slot == -1)
    356       return 2;
    357     setintV(L->top++, slot);
    358     return 3;
    359   }
    360   return 0;
    361 }
    362 
    363 /* local snap = jit.util.tracesnap(tr, sn) */
    364 LJLIB_CF(jit_util_tracesnap)
    365 {
    366   GCtrace *T = jit_checktrace(L);
    367   SnapNo sn = (SnapNo)lj_lib_checkint(L, 2);
    368   if (T && sn < T->nsnap) {
    369     SnapShot *snap = &T->snap[sn];
    370     SnapEntry *map = &T->snapmap[snap->mapofs];
    371     MSize n, nent = snap->nent;
    372     GCtab *t;
    373     lua_createtable(L, nent+2, 0);
    374     t = tabV(L->top-1);
    375     setintV(lj_tab_setint(L, t, 0), (int32_t)snap->ref - REF_BIAS);
    376     setintV(lj_tab_setint(L, t, 1), (int32_t)snap->nslots);
    377     for (n = 0; n < nent; n++)
    378       setintV(lj_tab_setint(L, t, (int32_t)(n+2)), (int32_t)map[n]);
    379     setintV(lj_tab_setint(L, t, (int32_t)(nent+2)), (int32_t)SNAP(255, 0, 0));
    380     return 1;
    381   }
    382   return 0;
    383 }
    384 
    385 /* local mcode, addr, loop = jit.util.tracemc(tr) */
    386 LJLIB_CF(jit_util_tracemc)
    387 {
    388   GCtrace *T = jit_checktrace(L);
    389   if (T && T->mcode != NULL) {
    390     setstrV(L, L->top-1, lj_str_new(L, (const char *)T->mcode, T->szmcode));
    391     setintptrV(L->top++, (intptr_t)(void *)T->mcode);
    392     setintV(L->top++, T->mcloop);
    393     return 3;
    394   }
    395   return 0;
    396 }
    397 
    398 /* local addr = jit.util.traceexitstub([tr,] exitno) */
    399 LJLIB_CF(jit_util_traceexitstub)
    400 {
    401 #ifdef EXITSTUBS_PER_GROUP
    402   ExitNo exitno = (ExitNo)lj_lib_checkint(L, 1);
    403   jit_State *J = L2J(L);
    404   if (exitno < EXITSTUBS_PER_GROUP*LJ_MAX_EXITSTUBGR) {
    405     setintptrV(L->top-1, (intptr_t)(void *)exitstub_addr(J, exitno));
    406     return 1;
    407   }
    408 #else
    409   if (L->top > L->base+1) {  /* Don't throw for one-argument variant. */
    410     GCtrace *T = jit_checktrace(L);
    411     ExitNo exitno = (ExitNo)lj_lib_checkint(L, 2);
    412     ExitNo maxexit = T->root ? T->nsnap+1 : T->nsnap;
    413     if (T && T->mcode != NULL && exitno < maxexit) {
    414       setintptrV(L->top-1, (intptr_t)(void *)exitstub_trace_addr(T, exitno));
    415       return 1;
    416     }
    417   }
    418 #endif
    419   return 0;
    420 }
    421 
    422 /* local addr = jit.util.ircalladdr(idx) */
    423 LJLIB_CF(jit_util_ircalladdr)
    424 {
    425   uint32_t idx = (uint32_t)lj_lib_checkint(L, 1);
    426   if (idx < IRCALL__MAX) {
    427     setintptrV(L->top-1, (intptr_t)(void *)lj_ir_callinfo[idx].func);
    428     return 1;
    429   }
    430   return 0;
    431 }
    432 
    433 #endif
    434 
    435 #include "lj_libdef.h"
    436 
    437 static int luaopen_jit_util(lua_State *L)
    438 {
    439   LJ_LIB_REG(L, NULL, jit_util);
    440   return 1;
    441 }
    442 
    443 /* -- jit.opt module ------------------------------------------------------ */
    444 
    445 #if LJ_HASJIT
    446 
    447 #define LJLIB_MODULE_jit_opt
    448 
    449 /* Parse optimization level. */
    450 static int jitopt_level(jit_State *J, const char *str)
    451 {
    452   if (str[0] >= '0' && str[0] <= '9' && str[1] == '\0') {
    453     uint32_t flags;
    454     if (str[0] == '0') flags = JIT_F_OPT_0;
    455     else if (str[0] == '1') flags = JIT_F_OPT_1;
    456     else if (str[0] == '2') flags = JIT_F_OPT_2;
    457     else flags = JIT_F_OPT_3;
    458     J->flags = (J->flags & ~JIT_F_OPT_MASK) | flags;
    459     return 1;  /* Ok. */
    460   }
    461   return 0;  /* No match. */
    462 }
    463 
    464 /* Parse optimization flag. */
    465 static int jitopt_flag(jit_State *J, const char *str)
    466 {
    467   const char *lst = JIT_F_OPTSTRING;
    468   uint32_t opt;
    469   int set = 1;
    470   if (str[0] == '+') {
    471     str++;
    472   } else if (str[0] == '-') {
    473     str++;
    474     set = 0;
    475   } else if (str[0] == 'n' && str[1] == 'o') {
    476     str += str[2] == '-' ? 3 : 2;
    477     set = 0;
    478   }
    479   for (opt = JIT_F_OPT_FIRST; ; opt <<= 1) {
    480     size_t len = *(const uint8_t *)lst;
    481     if (len == 0)
    482       break;
    483     if (strncmp(str, lst+1, len) == 0 && str[len] == '\0') {
    484       if (set) J->flags |= opt; else J->flags &= ~opt;
    485       return 1;  /* Ok. */
    486     }
    487     lst += 1+len;
    488   }
    489   return 0;  /* No match. */
    490 }
    491 
    492 /* Parse optimization parameter. */
    493 static int jitopt_param(jit_State *J, const char *str)
    494 {
    495   const char *lst = JIT_P_STRING;
    496   int i;
    497   for (i = 0; i < JIT_P__MAX; i++) {
    498     size_t len = *(const uint8_t *)lst;
    499     lua_assert(len != 0);
    500     if (strncmp(str, lst+1, len) == 0 && str[len] == '=') {
    501       int32_t n = 0;
    502       const char *p = &str[len+1];
    503       while (*p >= '0' && *p <= '9')
    504 	n = n*10 + (*p++ - '0');
    505       if (*p) return 0;  /* Malformed number. */
    506       J->param[i] = n;
    507       if (i == JIT_P_hotloop)
    508 	lj_dispatch_init_hotcount(J2G(J));
    509       return 1;  /* Ok. */
    510     }
    511     lst += 1+len;
    512   }
    513   return 0;  /* No match. */
    514 }
    515 
    516 /* jit.opt.start(flags...) */
    517 LJLIB_CF(jit_opt_start)
    518 {
    519   jit_State *J = L2J(L);
    520   int nargs = (int)(L->top - L->base);
    521   if (nargs == 0) {
    522     J->flags = (J->flags & ~JIT_F_OPT_MASK) | JIT_F_OPT_DEFAULT;
    523   } else {
    524     int i;
    525     for (i = 1; i <= nargs; i++) {
    526       const char *str = strdata(lj_lib_checkstr(L, i));
    527       if (!jitopt_level(J, str) &&
    528 	  !jitopt_flag(J, str) &&
    529 	  !jitopt_param(J, str))
    530 	lj_err_callerv(L, LJ_ERR_JITOPT, str);
    531     }
    532   }
    533   return 0;
    534 }
    535 
    536 #include "lj_libdef.h"
    537 
    538 #endif
    539 
    540 /* -- jit.profile module -------------------------------------------------- */
    541 
    542 #if LJ_HASPROFILE
    543 
    544 #define LJLIB_MODULE_jit_profile
    545 
    546 /* Not loaded by default, use: local profile = require("jit.profile") */
    547 
    548 static const char KEY_PROFILE_THREAD = 't';
    549 static const char KEY_PROFILE_FUNC = 'f';
    550 
    551 static void jit_profile_callback(lua_State *L2, lua_State *L, int samples,
    552 				 int vmstate)
    553 {
    554   TValue key;
    555   cTValue *tv;
    556   setlightudV(&key, (void *)&KEY_PROFILE_FUNC);
    557   tv = lj_tab_get(L, tabV(registry(L)), &key);
    558   if (tvisfunc(tv)) {
    559     char vmst = (char)vmstate;
    560     int status;
    561     setfuncV(L2, L2->top++, funcV(tv));
    562     setthreadV(L2, L2->top++, L);
    563     setintV(L2->top++, samples);
    564     setstrV(L2, L2->top++, lj_str_new(L2, &vmst, 1));
    565     status = lua_pcall(L2, 3, 0, 0);  /* callback(thread, samples, vmstate) */
    566     if (status) {
    567       if (G(L2)->panic) G(L2)->panic(L2);
    568       exit(EXIT_FAILURE);
    569     }
    570     lj_trace_abort(G(L2));
    571   }
    572 }
    573 
    574 /* profile.start(mode, cb) */
    575 LJLIB_CF(jit_profile_start)
    576 {
    577   GCtab *registry = tabV(registry(L));
    578   GCstr *mode = lj_lib_optstr(L, 1);
    579   GCfunc *func = lj_lib_checkfunc(L, 2);
    580   lua_State *L2 = lua_newthread(L);  /* Thread that runs profiler callback. */
    581   TValue key;
    582   /* Anchor thread and function in registry. */
    583   setlightudV(&key, (void *)&KEY_PROFILE_THREAD);
    584   setthreadV(L, lj_tab_set(L, registry, &key), L2);
    585   setlightudV(&key, (void *)&KEY_PROFILE_FUNC);
    586   setfuncV(L, lj_tab_set(L, registry, &key), func);
    587   lj_gc_anybarriert(L, registry);
    588   luaJIT_profile_start(L, mode ? strdata(mode) : "",
    589 		       (luaJIT_profile_callback)jit_profile_callback, L2);
    590   return 0;
    591 }
    592 
    593 /* profile.stop() */
    594 LJLIB_CF(jit_profile_stop)
    595 {
    596   GCtab *registry;
    597   TValue key;
    598   luaJIT_profile_stop(L);
    599   registry = tabV(registry(L));
    600   setlightudV(&key, (void *)&KEY_PROFILE_THREAD);
    601   setnilV(lj_tab_set(L, registry, &key));
    602   setlightudV(&key, (void *)&KEY_PROFILE_FUNC);
    603   setnilV(lj_tab_set(L, registry, &key));
    604   lj_gc_anybarriert(L, registry);
    605   return 0;
    606 }
    607 
    608 /* dump = profile.dumpstack([thread,] fmt, depth) */
    609 LJLIB_CF(jit_profile_dumpstack)
    610 {
    611   lua_State *L2 = L;
    612   int arg = 0;
    613   size_t len;
    614   int depth;
    615   GCstr *fmt;
    616   const char *p;
    617   if (L->top > L->base && tvisthread(L->base)) {
    618     L2 = threadV(L->base);
    619     arg = 1;
    620   }
    621   fmt = lj_lib_checkstr(L, arg+1);
    622   depth = lj_lib_checkint(L, arg+2);
    623   p = luaJIT_profile_dumpstack(L2, strdata(fmt), depth, &len);
    624   lua_pushlstring(L, p, len);
    625   return 1;
    626 }
    627 
    628 #include "lj_libdef.h"
    629 
    630 static int luaopen_jit_profile(lua_State *L)
    631 {
    632   LJ_LIB_REG(L, NULL, jit_profile);
    633   return 1;
    634 }
    635 
    636 #endif
    637 
    638 /* -- JIT compiler initialization ----------------------------------------- */
    639 
    640 #if LJ_HASJIT
    641 /* Default values for JIT parameters. */
    642 static const int32_t jit_param_default[JIT_P__MAX+1] = {
    643 #define JIT_PARAMINIT(len, name, value)	(value),
    644 JIT_PARAMDEF(JIT_PARAMINIT)
    645 #undef JIT_PARAMINIT
    646   0
    647 };
    648 #endif
    649 
    650 #if LJ_TARGET_ARM && LJ_TARGET_LINUX
    651 #include <sys/utsname.h>
    652 #endif
    653 
    654 /* Arch-dependent CPU detection. */
    655 static uint32_t jit_cpudetect(lua_State *L)
    656 {
    657   uint32_t flags = 0;
    658 #if LJ_TARGET_X86ORX64
    659   uint32_t vendor[4];
    660   uint32_t features[4];
    661   if (lj_vm_cpuid(0, vendor) && lj_vm_cpuid(1, features)) {
    662 #if !LJ_HASJIT
    663 #define JIT_F_SSE2	2
    664 #endif
    665     flags |= ((features[3] >> 26)&1) * JIT_F_SSE2;
    666 #if LJ_HASJIT
    667     flags |= ((features[2] >> 0)&1) * JIT_F_SSE3;
    668     flags |= ((features[2] >> 19)&1) * JIT_F_SSE4_1;
    669     if (vendor[2] == 0x6c65746e) {  /* Intel. */
    670       if ((features[0] & 0x0fff0ff0) == 0x000106c0)  /* Atom. */
    671 	flags |= JIT_F_LEA_AGU;
    672     } else if (vendor[2] == 0x444d4163) {  /* AMD. */
    673       uint32_t fam = (features[0] & 0x0ff00f00);
    674       if (fam >= 0x00000f00)  /* K8, K10. */
    675 	flags |= JIT_F_PREFER_IMUL;
    676     }
    677     if (vendor[0] >= 7) {
    678       uint32_t xfeatures[4];
    679       lj_vm_cpuid(7, xfeatures);
    680       flags |= ((xfeatures[1] >> 8)&1) * JIT_F_BMI2;
    681     }
    682 #endif
    683   }
    684   /* Check for required instruction set support on x86 (unnecessary on x64). */
    685 #if LJ_TARGET_X86
    686   if (!(flags & JIT_F_SSE2))
    687     luaL_error(L, "CPU with SSE2 required");
    688 #endif
    689 #elif LJ_TARGET_ARM
    690 #if LJ_HASJIT
    691   int ver = LJ_ARCH_VERSION;  /* Compile-time ARM CPU detection. */
    692 #if LJ_TARGET_LINUX
    693   if (ver < 70) {  /* Runtime ARM CPU detection. */
    694     struct utsname ut;
    695     uname(&ut);
    696     if (strncmp(ut.machine, "armv", 4) == 0) {
    697       if (ut.machine[4] >= '7')
    698 	ver = 70;
    699       else if (ut.machine[4] == '6')
    700 	ver = 60;
    701     }
    702   }
    703 #endif
    704   flags |= ver >= 70 ? JIT_F_ARMV7 :
    705 	   ver >= 61 ? JIT_F_ARMV6T2_ :
    706 	   ver >= 60 ? JIT_F_ARMV6_ : 0;
    707   flags |= LJ_ARCH_HASFPU == 0 ? 0 : ver >= 70 ? JIT_F_VFPV3 : JIT_F_VFPV2;
    708 #endif
    709 #elif LJ_TARGET_ARM64
    710   /* No optional CPU features to detect (for now). */
    711 #elif LJ_TARGET_PPC
    712 #if LJ_HASJIT
    713 #if LJ_ARCH_SQRT
    714   flags |= JIT_F_SQRT;
    715 #endif
    716 #if LJ_ARCH_ROUND
    717   flags |= JIT_F_ROUND;
    718 #endif
    719 #endif
    720 #elif LJ_TARGET_MIPS
    721 #if LJ_HASJIT
    722   /* Compile-time MIPS CPU detection. */
    723 #if LJ_ARCH_VERSION >= 20
    724   flags |= JIT_F_MIPSXXR2;
    725 #endif
    726   /* Runtime MIPS CPU detection. */
    727 #if defined(__GNUC__)
    728   if (!(flags & JIT_F_MIPSXXR2)) {
    729     int x;
    730 #ifdef __mips16
    731     x = 0;  /* Runtime detection is difficult. Ensure optimal -march flags. */
    732 #else
    733     /* On MIPS32R1 rotr is treated as srl. rotr r2,r2,1 -> srl r2,r2,1. */
    734     __asm__("li $2, 1\n\t.long 0x00221042\n\tmove %0, $2" : "=r"(x) : : "$2");
    735 #endif
    736     if (x) flags |= JIT_F_MIPSXXR2;  /* Either 0x80000000 (R2) or 0 (R1). */
    737   }
    738 #endif
    739 #endif
    740 #else
    741 #error "Missing CPU detection for this architecture"
    742 #endif
    743   UNUSED(L);
    744   return flags;
    745 }
    746 
    747 /* Initialize JIT compiler. */
    748 static void jit_init(lua_State *L)
    749 {
    750   uint32_t flags = jit_cpudetect(L);
    751 #if LJ_HASJIT
    752   jit_State *J = L2J(L);
    753   J->flags = flags | JIT_F_ON | JIT_F_OPT_DEFAULT;
    754   memcpy(J->param, jit_param_default, sizeof(J->param));
    755   lj_dispatch_update(G(L));
    756 #else
    757   UNUSED(flags);
    758 #endif
    759 }
    760 
    761 LUALIB_API int luaopen_jit(lua_State *L)
    762 {
    763   jit_init(L);
    764   lua_pushliteral(L, LJ_OS_NAME);
    765   lua_pushliteral(L, LJ_ARCH_NAME);
    766   lua_pushinteger(L, LUAJIT_VERSION_NUM);
    767   lua_pushliteral(L, LJ_LJX_VERSION);
    768   LJ_LIB_REG(L, LUA_JITLIBNAME, jit);
    769 #if LJ_HASPROFILE
    770   lj_lib_prereg(L, LUA_JITLIBNAME ".profile", luaopen_jit_profile,
    771 		tabref(L->env));
    772 #endif
    773 #ifndef LUAJIT_DISABLE_JITUTIL
    774   lj_lib_prereg(L, LUA_JITLIBNAME ".util", luaopen_jit_util, tabref(L->env));
    775 #endif
    776 #if LJ_HASJIT
    777   LJ_LIB_REG(L, "jit.opt", jit_opt);
    778   L->top -= 1;
    779 #endif
    780   return 1;
    781 }
    782