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