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