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 
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_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 
LJLIB_CF(jit_attach)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 
LJLIB_SET(os)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 
setintfield(lua_State * L,GCtab * t,const char * name,int32_t val)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]) */
LJLIB_CF(jit_util_funcinfo)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) */
LJLIB_CF(jit_util_funcbc)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) */
LJLIB_CF(jit_util_funck)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) */
LJLIB_CF(jit_util_funcuvname)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. */
jit_checktrace(lua_State * L)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) */
LJLIB_CF(jit_util_traceinfo)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) */
LJLIB_CF(jit_util_traceir)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) */
LJLIB_CF(jit_util_tracek)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) */
LJLIB_CF(jit_util_tracesnap)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) */
LJLIB_CF(jit_util_tracemc)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) */
LJLIB_CF(jit_util_traceexitstub)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) */
LJLIB_CF(jit_util_ircalladdr)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 
luaopen_jit_util(lua_State * L)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. */
jitopt_level(jit_State * J,const char * str)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. */
jitopt_flag(jit_State * J,const char * str)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. */
jitopt_param(jit_State * J,const char * str)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...) */
LJLIB_CF(jit_opt_start)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 
jit_profile_callback(lua_State * L2,lua_State * L,int samples,int vmstate)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) */
LJLIB_CF(jit_profile_start)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() */
LJLIB_CF(jit_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) */
LJLIB_CF(jit_profile_dumpstack)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 
luaopen_jit_profile(lua_State * L)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. */
jit_cpudetect(lua_State * L)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. */
jit_init(lua_State * L)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 
luaopen_jit(lua_State * L)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 
778