root/lib_jit.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. setjitmode
  2. LJLIB_CF
  3. LJLIB_CF
  4. LJLIB_CF
  5. flagbits_to_strings
  6. LJLIB_CF
  7. LJLIB_CF
  8. LJLIB_PUSH
  9. setintfield
  10. LJLIB_CF
  11. LJLIB_CF
  12. LJLIB_CF
  13. LJLIB_CF
  14. jit_checktrace
  15. LJLIB_CF
  16. LJLIB_CF
  17. LJLIB_CF
  18. LJLIB_CF
  19. LJLIB_CF
  20. LJLIB_CF
  21. LJLIB_CF
  22. luaopen_jit_util
  23. jitopt_level
  24. jitopt_flag
  25. jitopt_param
  26. LJLIB_CF
  27. jit_profile_callback
  28. LJLIB_CF
  29. LJLIB_CF
  30. LJLIB_CF
  31. luaopen_jit_profile
  32. jit_cpudetect
  33. jit_init
  34. luaopen_jit

   1 /*
   2 ** JIT library.
   3 ** Copyright (C) 2005-2017 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     lua_createtable(L, 0, 16);  /* Increment hash size if fields are added. */
 188     t = tabV(L->top-1);
 189     setintfield(L, t, "linedefined", pt->firstline);
 190     setintfield(L, t, "lastlinedefined", pt->firstline + pt->numline);
 191     setintfield(L, t, "stackslots", pt->framesize);
 192     setintfield(L, t, "params", pt->numparams);
 193     setintfield(L, t, "bytecodes", (int32_t)pt->sizebc);
 194     setintfield(L, t, "gcconsts", (int32_t)pt->sizekgc);
 195     setintfield(L, t, "nconsts", (int32_t)pt->sizekn);
 196     setintfield(L, t, "upvalues", (int32_t)pt->sizeuv);
 197     if (pc < pt->sizebc)
 198       setintfield(L, t, "currentline", lj_debug_line(pt, pc));
 199     lua_pushboolean(L, (pt->flags & PROTO_VARARG));
 200     lua_setfield(L, -2, "isvararg");
 201     lua_pushboolean(L, (pt->flags & PROTO_CHILD));
 202     lua_setfield(L, -2, "children");
 203     setstrV(L, L->top++, proto_chunkname(pt));
 204     lua_setfield(L, -2, "source");
 205     lj_debug_pushloc(L, pt, pc);
 206     lua_setfield(L, -2, "loc");
 207     setprotoV(L, lj_tab_setstr(L, t, lj_str_newlit(L, "proto")), pt);
 208   } else {
 209     GCfunc *fn = funcV(L->base);
 210     GCtab *t;
 211     lua_createtable(L, 0, 4);  /* Increment hash size if fields are added. */
 212     t = tabV(L->top-1);
 213     if (!iscfunc(fn))
 214       setintfield(L, t, "ffid", fn->c.ffid);
 215     setintptrV(lj_tab_setstr(L, t, lj_str_newlit(L, "addr")),
 216                (intptr_t)(void *)fn->c.f);
 217     setintfield(L, t, "upvalues", fn->c.nupvalues);
 218   }
 219   return 1;
 220 }
 221 
 222 /* local ins, m = jit.util.funcbc(func, pc) */
 223 LJLIB_CF(jit_util_funcbc)
 224 {
 225   GCproto *pt = check_Lproto(L, 0);
 226   BCPos pc = (BCPos)lj_lib_checkint(L, 2);
 227   if (pc < pt->sizebc) {
 228     BCIns ins = proto_bc(pt)[pc];
 229     BCOp op = bc_op(ins);
 230     lua_assert(op < BC__MAX);
 231     setintV(L->top, ins);
 232     setintV(L->top+1, lj_bc_mode[op]);
 233     L->top += 2;
 234     return 2;
 235   }
 236   return 0;
 237 }
 238 
 239 /* local k = jit.util.funck(func, idx) */
 240 LJLIB_CF(jit_util_funck)
 241 {
 242   GCproto *pt = check_Lproto(L, 0);
 243   ptrdiff_t idx = (ptrdiff_t)lj_lib_checkint(L, 2);
 244   if (idx >= 0) {
 245     if (idx < (ptrdiff_t)pt->sizekn) {
 246       copyTV(L, L->top-1, proto_knumtv(pt, idx));
 247       return 1;
 248     }
 249   } else {
 250     if (~idx < (ptrdiff_t)pt->sizekgc) {
 251       GCobj *gc = proto_kgc(pt, idx);
 252       setgcV(L, L->top-1, gc, ~gc->gch.gct);
 253       return 1;
 254     }
 255   }
 256   return 0;
 257 }
 258 
 259 /* local name = jit.util.funcuvname(func, idx) */
 260 LJLIB_CF(jit_util_funcuvname)
 261 {
 262   GCproto *pt = check_Lproto(L, 0);
 263   uint32_t idx = (uint32_t)lj_lib_checkint(L, 2);
 264   if (idx < pt->sizeuv) {
 265     setstrV(L, L->top-1, lj_str_newz(L, lj_debug_uvname(pt, idx)));
 266     return 1;
 267   }
 268   return 0;
 269 }
 270 
 271 /* -- Reflection API for traces ------------------------------------------- */
 272 
 273 #if LJ_HASJIT
 274 
 275 /* Check trace argument. Must not throw for non-existent trace numbers. */
 276 static GCtrace *jit_checktrace(lua_State *L)
 277 {
 278   TraceNo tr = (TraceNo)lj_lib_checkint(L, 1);
 279   jit_State *J = L2J(L);
 280   if (tr > 0 && tr < J->sizetrace)
 281     return traceref(J, tr);
 282   return NULL;
 283 }
 284 
 285 /* Names of link types. ORDER LJ_TRLINK */
 286 static const char *const jit_trlinkname[] = {
 287   "none", "root", "loop", "tail-recursion", "up-recursion", "down-recursion",
 288   "interpreter", "return", "stitch"
 289 };
 290 
 291 /* local info = jit.util.traceinfo(tr) */
 292 LJLIB_CF(jit_util_traceinfo)
 293 {
 294   GCtrace *T = jit_checktrace(L);
 295   if (T) {
 296     GCtab *t;
 297     lua_createtable(L, 0, 8);  /* Increment hash size if fields are added. */
 298     t = tabV(L->top-1);
 299     setintfield(L, t, "nins", (int32_t)T->nins - REF_BIAS - 1);
 300     setintfield(L, t, "nk", REF_BIAS - (int32_t)T->nk);
 301     setintfield(L, t, "link", T->link);
 302     setintfield(L, t, "nexit", T->nsnap);
 303     setstrV(L, L->top++, lj_str_newz(L, jit_trlinkname[T->linktype]));
 304     lua_setfield(L, -2, "linktype");
 305     /* There are many more fields. Add them only when needed. */
 306     return 1;
 307   }
 308   return 0;
 309 }
 310 
 311 /* local m, ot, op1, op2, prev = jit.util.traceir(tr, idx) */
 312 LJLIB_CF(jit_util_traceir)
 313 {
 314   GCtrace *T = jit_checktrace(L);
 315   IRRef ref = (IRRef)lj_lib_checkint(L, 2) + REF_BIAS;
 316   if (T && ref >= REF_BIAS && ref < T->nins) {
 317     IRIns *ir = &T->ir[ref];
 318     int32_t m = lj_ir_mode[ir->o];
 319     setintV(L->top-2, m);
 320     setintV(L->top-1, ir->ot);
 321     setintV(L->top++, (int32_t)ir->op1 - (irm_op1(m)==IRMref ? REF_BIAS : 0));
 322     setintV(L->top++, (int32_t)ir->op2 - (irm_op2(m)==IRMref ? REF_BIAS : 0));
 323     setintV(L->top++, ir->prev);
 324     return 5;
 325   }
 326   return 0;
 327 }
 328 
 329 /* local k, t [, slot] = jit.util.tracek(tr, idx) */
 330 LJLIB_CF(jit_util_tracek)
 331 {
 332   GCtrace *T = jit_checktrace(L);
 333   IRRef ref = (IRRef)lj_lib_checkint(L, 2) + REF_BIAS;
 334   if (T && ref >= T->nk && ref < REF_BIAS) {
 335     IRIns *ir = &T->ir[ref];
 336     int32_t slot = -1;
 337     if (ir->o == IR_KSLOT) {
 338       slot = ir->op2;
 339       ir = &T->ir[ir->op1];
 340     }
 341 #if LJ_HASFFI
 342     if (ir->o == IR_KINT64 && !ctype_ctsG(G(L))) {
 343       ptrdiff_t oldtop = savestack(L, L->top);
 344       luaopen_ffi(L);  /* Load FFI library on-demand. */
 345       L->top = restorestack(L, oldtop);
 346     }
 347 #endif
 348     lj_ir_kvalue(L, L->top-2, ir);
 349     setintV(L->top-1, (int32_t)irt_type(ir->t));
 350     if (slot == -1)
 351       return 2;
 352     setintV(L->top++, slot);
 353     return 3;
 354   }
 355   return 0;
 356 }
 357 
 358 /* local snap = jit.util.tracesnap(tr, sn) */
 359 LJLIB_CF(jit_util_tracesnap)
 360 {
 361   GCtrace *T = jit_checktrace(L);
 362   SnapNo sn = (SnapNo)lj_lib_checkint(L, 2);
 363   if (T && sn < T->nsnap) {
 364     SnapShot *snap = &T->snap[sn];
 365     SnapEntry *map = &T->snapmap[snap->mapofs];
 366     MSize n, nent = snap->nent;
 367     GCtab *t;
 368     lua_createtable(L, nent+2, 0);
 369     t = tabV(L->top-1);
 370     setintV(lj_tab_setint(L, t, 0), (int32_t)snap->ref - REF_BIAS);
 371     setintV(lj_tab_setint(L, t, 1), (int32_t)snap->nslots);
 372     for (n = 0; n < nent; n++)
 373       setintV(lj_tab_setint(L, t, (int32_t)(n+2)), (int32_t)map[n]);
 374     setintV(lj_tab_setint(L, t, (int32_t)(nent+2)), (int32_t)SNAP(255, 0, 0));
 375     return 1;
 376   }
 377   return 0;
 378 }
 379 
 380 /* local mcode, addr, loop = jit.util.tracemc(tr) */
 381 LJLIB_CF(jit_util_tracemc)
 382 {
 383   GCtrace *T = jit_checktrace(L);
 384   if (T && T->mcode != NULL) {
 385     setstrV(L, L->top-1, lj_str_new(L, (const char *)T->mcode, T->szmcode));
 386     setintptrV(L->top++, (intptr_t)(void *)T->mcode);
 387     setintV(L->top++, T->mcloop);
 388     return 3;
 389   }
 390   return 0;
 391 }
 392 
 393 /* local addr = jit.util.traceexitstub([tr,] exitno) */
 394 LJLIB_CF(jit_util_traceexitstub)
 395 {
 396 #ifdef EXITSTUBS_PER_GROUP
 397   ExitNo exitno = (ExitNo)lj_lib_checkint(L, 1);
 398   jit_State *J = L2J(L);
 399   if (exitno < EXITSTUBS_PER_GROUP*LJ_MAX_EXITSTUBGR) {
 400     setintptrV(L->top-1, (intptr_t)(void *)exitstub_addr(J, exitno));
 401     return 1;
 402   }
 403 #else
 404   if (L->top > L->base+1) {  /* Don't throw for one-argument variant. */
 405     GCtrace *T = jit_checktrace(L);
 406     ExitNo exitno = (ExitNo)lj_lib_checkint(L, 2);
 407     ExitNo maxexit = T->root ? T->nsnap+1 : T->nsnap;
 408     if (T && T->mcode != NULL && exitno < maxexit) {
 409       setintptrV(L->top-1, (intptr_t)(void *)exitstub_trace_addr(T, exitno));
 410       return 1;
 411     }
 412   }
 413 #endif
 414   return 0;
 415 }
 416 
 417 /* local addr = jit.util.ircalladdr(idx) */
 418 LJLIB_CF(jit_util_ircalladdr)
 419 {
 420   uint32_t idx = (uint32_t)lj_lib_checkint(L, 1);
 421   if (idx < IRCALL__MAX) {
 422     setintptrV(L->top-1, (intptr_t)(void *)lj_ir_callinfo[idx].func);
 423     return 1;
 424   }
 425   return 0;
 426 }
 427 
 428 #endif
 429 
 430 #include "lj_libdef.h"
 431 
 432 static int luaopen_jit_util(lua_State *L)
 433 {
 434   LJ_LIB_REG(L, NULL, jit_util);
 435   return 1;
 436 }
 437 
 438 /* -- jit.opt module ------------------------------------------------------ */
 439 
 440 #if LJ_HASJIT
 441 
 442 #define LJLIB_MODULE_jit_opt
 443 
 444 /* Parse optimization level. */
 445 static int jitopt_level(jit_State *J, const char *str)
 446 {
 447   if (str[0] >= '0' && str[0] <= '9' && str[1] == '\0') {
 448     uint32_t flags;
 449     if (str[0] == '0') flags = JIT_F_OPT_0;
 450     else if (str[0] == '1') flags = JIT_F_OPT_1;
 451     else if (str[0] == '2') flags = JIT_F_OPT_2;
 452     else flags = JIT_F_OPT_3;
 453     J->flags = (J->flags & ~JIT_F_OPT_MASK) | flags;
 454     return 1;  /* Ok. */
 455   }
 456   return 0;  /* No match. */
 457 }
 458 
 459 /* Parse optimization flag. */
 460 static int jitopt_flag(jit_State *J, const char *str)
 461 {
 462   const char *lst = JIT_F_OPTSTRING;
 463   uint32_t opt;
 464   int set = 1;
 465   if (str[0] == '+') {
 466     str++;
 467   } else if (str[0] == '-') {
 468     str++;
 469     set = 0;
 470   } else if (str[0] == 'n' && str[1] == 'o') {
 471     str += str[2] == '-' ? 3 : 2;
 472     set = 0;
 473   }
 474   for (opt = JIT_F_OPT_FIRST; ; opt <<= 1) {
 475     size_t len = *(const uint8_t *)lst;
 476     if (len == 0)
 477       break;
 478     if (strncmp(str, lst+1, len) == 0 && str[len] == '\0') {
 479       if (set) J->flags |= opt; else J->flags &= ~opt;
 480       return 1;  /* Ok. */
 481     }
 482     lst += 1+len;
 483   }
 484   return 0;  /* No match. */
 485 }
 486 
 487 /* Parse optimization parameter. */
 488 static int jitopt_param(jit_State *J, const char *str)
 489 {
 490   const char *lst = JIT_P_STRING;
 491   int i;
 492   for (i = 0; i < JIT_P__MAX; i++) {
 493     size_t len = *(const uint8_t *)lst;
 494     lua_assert(len != 0);
 495     if (strncmp(str, lst+1, len) == 0 && str[len] == '=') {
 496       int32_t n = 0;
 497       const char *p = &str[len+1];
 498       while (*p >= '0' && *p <= '9')
 499         n = n*10 + (*p++ - '0');
 500       if (*p) return 0;  /* Malformed number. */
 501       J->param[i] = n;
 502       if (i == JIT_P_hotloop)
 503         lj_dispatch_init_hotcount(J2G(J));
 504       return 1;  /* Ok. */
 505     }
 506     lst += 1+len;
 507   }
 508   return 0;  /* No match. */
 509 }
 510 
 511 /* jit.opt.start(flags...) */
 512 LJLIB_CF(jit_opt_start)
 513 {
 514   jit_State *J = L2J(L);
 515   int nargs = (int)(L->top - L->base);
 516   if (nargs == 0) {
 517     J->flags = (J->flags & ~JIT_F_OPT_MASK) | JIT_F_OPT_DEFAULT;
 518   } else {
 519     int i;
 520     for (i = 1; i <= nargs; i++) {
 521       const char *str = strdata(lj_lib_checkstr(L, i));
 522       if (!jitopt_level(J, str) &&
 523           !jitopt_flag(J, str) &&
 524           !jitopt_param(J, str))
 525         lj_err_callerv(L, LJ_ERR_JITOPT, str);
 526     }
 527   }
 528   return 0;
 529 }
 530 
 531 #include "lj_libdef.h"
 532 
 533 #endif
 534 
 535 /* -- jit.profile module -------------------------------------------------- */
 536 
 537 #if LJ_HASPROFILE
 538 
 539 #define LJLIB_MODULE_jit_profile
 540 
 541 /* Not loaded by default, use: local profile = require("jit.profile") */
 542 
 543 static const char KEY_PROFILE_THREAD = 't';
 544 static const char KEY_PROFILE_FUNC = 'f';
 545 
 546 static void jit_profile_callback(lua_State *L2, lua_State *L, int samples,
 547                                  int vmstate)
 548 {
 549   TValue key;
 550   cTValue *tv;
 551   setlightudV(&key, (void *)&KEY_PROFILE_FUNC);
 552   tv = lj_tab_get(L, tabV(registry(L)), &key);
 553   if (tvisfunc(tv)) {
 554     char vmst = (char)vmstate;
 555     int status;
 556     setfuncV(L2, L2->top++, funcV(tv));
 557     setthreadV(L2, L2->top++, L);
 558     setintV(L2->top++, samples);
 559     setstrV(L2, L2->top++, lj_str_new(L2, &vmst, 1));
 560     status = lua_pcall(L2, 3, 0, 0);  /* callback(thread, samples, vmstate) */
 561     if (status) {
 562       if (G(L2)->panic) G(L2)->panic(L2);
 563       exit(EXIT_FAILURE);
 564     }
 565     lj_trace_abort(G(L2));
 566   }
 567 }
 568 
 569 /* profile.start(mode, cb) */
 570 LJLIB_CF(jit_profile_start)
 571 {
 572   GCtab *registry = tabV(registry(L));
 573   GCstr *mode = lj_lib_optstr(L, 1);
 574   GCfunc *func = lj_lib_checkfunc(L, 2);
 575   lua_State *L2 = lua_newthread(L);  /* Thread that runs profiler callback. */
 576   TValue key;
 577   /* Anchor thread and function in registry. */
 578   setlightudV(&key, (void *)&KEY_PROFILE_THREAD);
 579   setthreadV(L, lj_tab_set(L, registry, &key), L2);
 580   setlightudV(&key, (void *)&KEY_PROFILE_FUNC);
 581   setfuncV(L, lj_tab_set(L, registry, &key), func);
 582   lj_gc_anybarriert(L, registry);
 583   luaJIT_profile_start(L, mode ? strdata(mode) : "",
 584                        (luaJIT_profile_callback)jit_profile_callback, L2);
 585   return 0;
 586 }
 587 
 588 /* profile.stop() */
 589 LJLIB_CF(jit_profile_stop)
 590 {
 591   GCtab *registry;
 592   TValue key;
 593   luaJIT_profile_stop(L);
 594   registry = tabV(registry(L));
 595   setlightudV(&key, (void *)&KEY_PROFILE_THREAD);
 596   setnilV(lj_tab_set(L, registry, &key));
 597   setlightudV(&key, (void *)&KEY_PROFILE_FUNC);
 598   setnilV(lj_tab_set(L, registry, &key));
 599   lj_gc_anybarriert(L, registry);
 600   return 0;
 601 }
 602 
 603 /* dump = profile.dumpstack([thread,] fmt, depth) */
 604 LJLIB_CF(jit_profile_dumpstack)
 605 {
 606   lua_State *L2 = L;
 607   int arg = 0;
 608   size_t len;
 609   int depth;
 610   GCstr *fmt;
 611   const char *p;
 612   if (L->top > L->base && tvisthread(L->base)) {
 613     L2 = threadV(L->base);
 614     arg = 1;
 615   }
 616   fmt = lj_lib_checkstr(L, arg+1);
 617   depth = lj_lib_checkint(L, arg+2);
 618   p = luaJIT_profile_dumpstack(L2, strdata(fmt), depth, &len);
 619   lua_pushlstring(L, p, len);
 620   return 1;
 621 }
 622 
 623 #include "lj_libdef.h"
 624 
 625 static int luaopen_jit_profile(lua_State *L)
 626 {
 627   LJ_LIB_REG(L, NULL, jit_profile);
 628   return 1;
 629 }
 630 
 631 #endif
 632 
 633 /* -- JIT compiler initialization ----------------------------------------- */
 634 
 635 #if LJ_HASJIT
 636 /* Default values for JIT parameters. */
 637 static const int32_t jit_param_default[JIT_P__MAX+1] = {
 638 #define JIT_PARAMINIT(len, name, value) (value),
 639 JIT_PARAMDEF(JIT_PARAMINIT)
 640 #undef JIT_PARAMINIT
 641   0
 642 };
 643 #endif
 644 
 645 #if LJ_TARGET_ARM && LJ_TARGET_LINUX
 646 #include <sys/utsname.h>
 647 #endif
 648 
 649 /* Arch-dependent CPU detection. */
 650 static uint32_t jit_cpudetect(lua_State *L)
 651 {
 652   uint32_t flags = 0;
 653 #if LJ_TARGET_X86ORX64
 654   uint32_t vendor[4];
 655   uint32_t features[4];
 656   if (lj_vm_cpuid(0, vendor) && lj_vm_cpuid(1, features)) {
 657 #if !LJ_HASJIT
 658 #define JIT_F_SSE2      2
 659 #endif
 660     flags |= ((features[3] >> 26)&1) * JIT_F_SSE2;
 661 #if LJ_HASJIT
 662     flags |= ((features[2] >> 0)&1) * JIT_F_SSE3;
 663     flags |= ((features[2] >> 19)&1) * JIT_F_SSE4_1;
 664     if (vendor[2] == 0x6c65746e) {  /* Intel. */
 665       if ((features[0] & 0x0fff0ff0) == 0x000106c0)  /* Atom. */
 666         flags |= JIT_F_LEA_AGU;
 667     } else if (vendor[2] == 0x444d4163) {  /* AMD. */
 668       uint32_t fam = (features[0] & 0x0ff00f00);
 669       if (fam >= 0x00000f00)  /* K8, K10. */
 670         flags |= JIT_F_PREFER_IMUL;
 671     }
 672     if (vendor[0] >= 7) {
 673       uint32_t xfeatures[4];
 674       lj_vm_cpuid(7, xfeatures);
 675       flags |= ((xfeatures[1] >> 8)&1) * JIT_F_BMI2;
 676     }
 677 #endif
 678   }
 679   /* Check for required instruction set support on x86 (unnecessary on x64). */
 680 #if LJ_TARGET_X86
 681   if (!(flags & JIT_F_SSE2))
 682     luaL_error(L, "CPU with SSE2 required");
 683 #endif
 684 #elif LJ_TARGET_ARM
 685 #if LJ_HASJIT
 686   int ver = LJ_ARCH_VERSION;  /* Compile-time ARM CPU detection. */
 687 #if LJ_TARGET_LINUX
 688   if (ver < 70) {  /* Runtime ARM CPU detection. */
 689     struct utsname ut;
 690     uname(&ut);
 691     if (strncmp(ut.machine, "armv", 4) == 0) {
 692       if (ut.machine[4] >= '7')
 693         ver = 70;
 694       else if (ut.machine[4] == '6')
 695         ver = 60;
 696     }
 697   }
 698 #endif
 699   flags |= ver >= 70 ? JIT_F_ARMV7 :
 700            ver >= 61 ? JIT_F_ARMV6T2_ :
 701            ver >= 60 ? JIT_F_ARMV6_ : 0;
 702   flags |= LJ_ARCH_HASFPU == 0 ? 0 : ver >= 70 ? JIT_F_VFPV3 : JIT_F_VFPV2;
 703 #endif
 704 #elif LJ_TARGET_ARM64
 705   /* No optional CPU features to detect (for now). */
 706 #elif LJ_TARGET_PPC
 707 #if LJ_HASJIT
 708 #if LJ_ARCH_SQRT
 709   flags |= JIT_F_SQRT;
 710 #endif
 711 #if LJ_ARCH_ROUND
 712   flags |= JIT_F_ROUND;
 713 #endif
 714 #endif
 715 #elif LJ_TARGET_MIPS
 716 #if LJ_HASJIT
 717   /* Compile-time MIPS CPU detection. */
 718 #if LJ_ARCH_VERSION >= 20
 719   flags |= JIT_F_MIPSXXR2;
 720 #endif
 721   /* Runtime MIPS CPU detection. */
 722 #if defined(__GNUC__)
 723   if (!(flags & JIT_F_MIPSXXR2)) {
 724     int x;
 725 #ifdef __mips16
 726     x = 0;  /* Runtime detection is difficult. Ensure optimal -march flags. */
 727 #else
 728     /* On MIPS32R1 rotr is treated as srl. rotr r2,r2,1 -> srl r2,r2,1. */
 729     __asm__("li $2, 1\n\t.long 0x00221042\n\tmove %0, $2" : "=r"(x) : : "$2");
 730 #endif
 731     if (x) flags |= JIT_F_MIPSXXR2;  /* Either 0x80000000 (R2) or 0 (R1). */
 732   }
 733 #endif
 734 #endif
 735 #else
 736 #error "Missing CPU detection for this architecture"
 737 #endif
 738   UNUSED(L);
 739   return flags;
 740 }
 741 
 742 /* Initialize JIT compiler. */
 743 static void jit_init(lua_State *L)
 744 {
 745   uint32_t flags = jit_cpudetect(L);
 746 #if LJ_HASJIT
 747   jit_State *J = L2J(L);
 748   J->flags = flags | JIT_F_ON | JIT_F_OPT_DEFAULT;
 749   memcpy(J->param, jit_param_default, sizeof(J->param));
 750   lj_dispatch_update(G(L));
 751 #else
 752   UNUSED(flags);
 753 #endif
 754 }
 755 
 756 LUALIB_API int luaopen_jit(lua_State *L)
 757 {
 758   jit_init(L);
 759   lua_pushliteral(L, LJ_OS_NAME);
 760   lua_pushliteral(L, LJ_ARCH_NAME);
 761   lua_pushinteger(L, LUAJIT_VERSION_NUM);
 762   lua_pushliteral(L, LUAJIT_VERSION);
 763   LJ_LIB_REG(L, LUA_JITLIBNAME, jit);
 764 #if LJ_HASPROFILE
 765   lj_lib_prereg(L, LUA_JITLIBNAME ".profile", luaopen_jit_profile,
 766                 tabref(L->env));
 767 #endif
 768 #ifndef LUAJIT_DISABLE_JITUTIL
 769   lj_lib_prereg(L, LUA_JITLIBNAME ".util", luaopen_jit_util, tabref(L->env));
 770 #endif
 771 #if LJ_HASJIT
 772   LJ_LIB_REG(L, "jit.opt", jit_opt);
 773 #endif
 774   L->top -= 2;
 775   return 1;
 776 }
 777 

/* [<][>][^][v][top][bottom][index][help] */