OSX/iOS: Fix SDK incompatibility.
[luajit-2.0.git] / src / lib_jit.c
blobb83c865a475535c53750c3b347a5e499a44bff80
1 /*
2 ** JIT library.
3 ** Copyright (C) 2005-2023 Mike Pall. See Copyright Notice in luajit.h
4 */
6 #define lib_jit_c
7 #define LUA_LIB
9 #include "lua.h"
10 #include "lauxlib.h"
11 #include "lualib.h"
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"
37 #include "luajit.h"
39 /* -- jit.* functions ----------------------------------------------------- */
41 #define LJLIB_MODULE_jit
43 static int setjitmode(lua_State *L, int mode)
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;
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);
65 return 0;
68 LJLIB_CF(jit_on)
70 return setjitmode(L, LUAJIT_MODE_ON);
73 LJLIB_CF(jit_off)
75 return setjitmode(L, LUAJIT_MODE_OFF);
78 LJLIB_CF(jit_flush)
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;
86 #endif
87 return setjitmode(L, LUAJIT_MODE_FLUSH);
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)
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));
99 #endif
101 LJLIB_CF(jit_status)
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
116 LJLIB_CF(jit_security)
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;
123 LJLIB_CF(jit_attach)
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));
147 #endif
148 return 0;
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)
156 #include "lj_libdef.h"
158 /* -- jit.util.* functions ------------------------------------------------ */
160 #define LJLIB_MODULE_jit_util
162 /* -- Reflection API for Lua functions ------------------------------------ */
164 static void setintfield(lua_State *L, GCtab *t, const char *name, int32_t val)
166 setintV(lj_tab_setstr(L, t, lj_str_newz(L, name)), val);
169 /* local info = jit.util.funcinfo(func [,pc]) */
170 LJLIB_CF(jit_util_funcinfo)
172 GCproto *pt = lj_lib_checkLproto(L, 1, 1);
173 if (pt) {
174 BCPos pc = (BCPos)lj_lib_optint(L, 2, 0);
175 GCtab *t;
176 lua_createtable(L, 0, 16); /* Increment hash size if fields are added. */
177 t = tabV(L->top-1);
178 setintfield(L, t, "linedefined", pt->firstline);
179 setintfield(L, t, "lastlinedefined", pt->firstline + pt->numline);
180 setintfield(L, t, "stackslots", pt->framesize);
181 setintfield(L, t, "params", pt->numparams);
182 setintfield(L, t, "bytecodes", (int32_t)pt->sizebc);
183 setintfield(L, t, "gcconsts", (int32_t)pt->sizekgc);
184 setintfield(L, t, "nconsts", (int32_t)pt->sizekn);
185 setintfield(L, t, "upvalues", (int32_t)pt->sizeuv);
186 if (pc < pt->sizebc)
187 setintfield(L, t, "currentline", lj_debug_line(pt, pc));
188 lua_pushboolean(L, (pt->flags & PROTO_VARARG));
189 lua_setfield(L, -2, "isvararg");
190 lua_pushboolean(L, (pt->flags & PROTO_CHILD));
191 lua_setfield(L, -2, "children");
192 setstrV(L, L->top++, proto_chunkname(pt));
193 lua_setfield(L, -2, "source");
194 lj_debug_pushloc(L, pt, pc);
195 lua_setfield(L, -2, "loc");
196 setprotoV(L, lj_tab_setstr(L, t, lj_str_newlit(L, "proto")), pt);
197 } else {
198 GCfunc *fn = funcV(L->base);
199 GCtab *t;
200 lua_createtable(L, 0, 4); /* Increment hash size if fields are added. */
201 t = tabV(L->top-1);
202 if (!iscfunc(fn))
203 setintfield(L, t, "ffid", fn->c.ffid);
204 setintptrV(lj_tab_setstr(L, t, lj_str_newlit(L, "addr")),
205 (intptr_t)(void *)fn->c.f);
206 setintfield(L, t, "upvalues", fn->c.nupvalues);
208 return 1;
211 /* local ins, m = jit.util.funcbc(func, pc) */
212 LJLIB_CF(jit_util_funcbc)
214 GCproto *pt = lj_lib_checkLproto(L, 1, 0);
215 BCPos pc = (BCPos)lj_lib_checkint(L, 2);
216 if (pc < pt->sizebc) {
217 BCIns ins = proto_bc(pt)[pc];
218 BCOp op = bc_op(ins);
219 lj_assertL(op < BC__MAX, "bad bytecode op %d", op);
220 setintV(L->top, ins);
221 setintV(L->top+1, lj_bc_mode[op]);
222 L->top += 2;
223 return 2;
225 return 0;
228 /* local k = jit.util.funck(func, idx) */
229 LJLIB_CF(jit_util_funck)
231 GCproto *pt = lj_lib_checkLproto(L, 1, 0);
232 ptrdiff_t idx = (ptrdiff_t)lj_lib_checkint(L, 2);
233 if (idx >= 0) {
234 if (idx < (ptrdiff_t)pt->sizekn) {
235 copyTV(L, L->top-1, proto_knumtv(pt, idx));
236 return 1;
238 } else {
239 if (~idx < (ptrdiff_t)pt->sizekgc) {
240 GCobj *gc = proto_kgc(pt, idx);
241 setgcV(L, L->top-1, gc, ~gc->gch.gct);
242 return 1;
245 return 0;
248 /* local name = jit.util.funcuvname(func, idx) */
249 LJLIB_CF(jit_util_funcuvname)
251 GCproto *pt = lj_lib_checkLproto(L, 1, 0);
252 uint32_t idx = (uint32_t)lj_lib_checkint(L, 2);
253 if (idx < pt->sizeuv) {
254 setstrV(L, L->top-1, lj_str_newz(L, lj_debug_uvname(pt, idx)));
255 return 1;
257 return 0;
260 /* -- Reflection API for traces ------------------------------------------- */
262 #if LJ_HASJIT
264 /* Check trace argument. Must not throw for non-existent trace numbers. */
265 static GCtrace *jit_checktrace(lua_State *L)
267 TraceNo tr = (TraceNo)lj_lib_checkint(L, 1);
268 jit_State *J = L2J(L);
269 if (tr > 0 && tr < J->sizetrace)
270 return traceref(J, tr);
271 return NULL;
274 /* Names of link types. ORDER LJ_TRLINK */
275 static const char *const jit_trlinkname[] = {
276 "none", "root", "loop", "tail-recursion", "up-recursion", "down-recursion",
277 "interpreter", "return", "stitch"
280 /* local info = jit.util.traceinfo(tr) */
281 LJLIB_CF(jit_util_traceinfo)
283 GCtrace *T = jit_checktrace(L);
284 if (T) {
285 GCtab *t;
286 lua_createtable(L, 0, 8); /* Increment hash size if fields are added. */
287 t = tabV(L->top-1);
288 setintfield(L, t, "nins", (int32_t)T->nins - REF_BIAS - 1);
289 setintfield(L, t, "nk", REF_BIAS - (int32_t)T->nk);
290 setintfield(L, t, "link", T->link);
291 setintfield(L, t, "nexit", T->nsnap);
292 setstrV(L, L->top++, lj_str_newz(L, jit_trlinkname[T->linktype]));
293 lua_setfield(L, -2, "linktype");
294 /* There are many more fields. Add them only when needed. */
295 return 1;
297 return 0;
300 /* local m, ot, op1, op2, prev = jit.util.traceir(tr, idx) */
301 LJLIB_CF(jit_util_traceir)
303 GCtrace *T = jit_checktrace(L);
304 IRRef ref = (IRRef)lj_lib_checkint(L, 2) + REF_BIAS;
305 if (T && ref >= REF_BIAS && ref < T->nins) {
306 IRIns *ir = &T->ir[ref];
307 int32_t m = lj_ir_mode[ir->o];
308 setintV(L->top-2, m);
309 setintV(L->top-1, ir->ot);
310 setintV(L->top++, (int32_t)ir->op1 - (irm_op1(m)==IRMref ? REF_BIAS : 0));
311 setintV(L->top++, (int32_t)ir->op2 - (irm_op2(m)==IRMref ? REF_BIAS : 0));
312 setintV(L->top++, ir->prev);
313 return 5;
315 return 0;
318 /* local k, t [, slot] = jit.util.tracek(tr, idx) */
319 LJLIB_CF(jit_util_tracek)
321 GCtrace *T = jit_checktrace(L);
322 IRRef ref = (IRRef)lj_lib_checkint(L, 2) + REF_BIAS;
323 if (T && ref >= T->nk && ref < REF_BIAS) {
324 IRIns *ir = &T->ir[ref];
325 int32_t slot = -1;
326 if (ir->o == IR_KSLOT) {
327 slot = ir->op2;
328 ir = &T->ir[ir->op1];
330 #if LJ_HASFFI
331 if (ir->o == IR_KINT64) ctype_loadffi(L);
332 #endif
333 lj_ir_kvalue(L, L->top-2, ir);
334 setintV(L->top-1, (int32_t)irt_type(ir->t));
335 if (slot == -1)
336 return 2;
337 setintV(L->top++, slot);
338 return 3;
340 return 0;
343 /* local snap = jit.util.tracesnap(tr, sn) */
344 LJLIB_CF(jit_util_tracesnap)
346 GCtrace *T = jit_checktrace(L);
347 SnapNo sn = (SnapNo)lj_lib_checkint(L, 2);
348 if (T && sn < T->nsnap) {
349 SnapShot *snap = &T->snap[sn];
350 SnapEntry *map = &T->snapmap[snap->mapofs];
351 MSize n, nent = snap->nent;
352 GCtab *t;
353 lua_createtable(L, nent+2, 0);
354 t = tabV(L->top-1);
355 setintV(lj_tab_setint(L, t, 0), (int32_t)snap->ref - REF_BIAS);
356 setintV(lj_tab_setint(L, t, 1), (int32_t)snap->nslots);
357 for (n = 0; n < nent; n++)
358 setintV(lj_tab_setint(L, t, (int32_t)(n+2)), (int32_t)map[n]);
359 setintV(lj_tab_setint(L, t, (int32_t)(nent+2)), (int32_t)SNAP(255, 0, 0));
360 return 1;
362 return 0;
365 /* local mcode, addr, loop = jit.util.tracemc(tr) */
366 LJLIB_CF(jit_util_tracemc)
368 GCtrace *T = jit_checktrace(L);
369 if (T && T->mcode != NULL) {
370 setstrV(L, L->top-1, lj_str_new(L, (const char *)T->mcode, T->szmcode));
371 setintptrV(L->top++, (intptr_t)(void *)T->mcode);
372 setintV(L->top++, T->mcloop);
373 return 3;
375 return 0;
378 /* local addr = jit.util.traceexitstub([tr,] exitno) */
379 LJLIB_CF(jit_util_traceexitstub)
381 #ifdef EXITSTUBS_PER_GROUP
382 ExitNo exitno = (ExitNo)lj_lib_checkint(L, 1);
383 jit_State *J = L2J(L);
384 if (exitno < EXITSTUBS_PER_GROUP*LJ_MAX_EXITSTUBGR) {
385 setintptrV(L->top-1, (intptr_t)(void *)exitstub_addr(J, exitno));
386 return 1;
388 #else
389 if (L->top > L->base+1) { /* Don't throw for one-argument variant. */
390 GCtrace *T = jit_checktrace(L);
391 ExitNo exitno = (ExitNo)lj_lib_checkint(L, 2);
392 ExitNo maxexit = T->root ? T->nsnap+1 : T->nsnap;
393 if (T && T->mcode != NULL && exitno < maxexit) {
394 setintptrV(L->top-1, (intptr_t)(void *)exitstub_trace_addr(T, exitno));
395 return 1;
398 #endif
399 return 0;
402 /* local addr = jit.util.ircalladdr(idx) */
403 LJLIB_CF(jit_util_ircalladdr)
405 uint32_t idx = (uint32_t)lj_lib_checkint(L, 1);
406 if (idx < IRCALL__MAX) {
407 ASMFunction func = lj_ir_callinfo[idx].func;
408 setintptrV(L->top-1, (intptr_t)(void *)lj_ptr_strip(func));
409 return 1;
411 return 0;
414 #endif
416 #include "lj_libdef.h"
418 static int luaopen_jit_util(lua_State *L)
420 LJ_LIB_REG(L, NULL, jit_util);
421 return 1;
424 /* -- jit.opt module ------------------------------------------------------ */
426 #if LJ_HASJIT
428 #define LJLIB_MODULE_jit_opt
430 /* Parse optimization level. */
431 static int jitopt_level(jit_State *J, const char *str)
433 if (str[0] >= '0' && str[0] <= '9' && str[1] == '\0') {
434 uint32_t flags;
435 if (str[0] == '0') flags = JIT_F_OPT_0;
436 else if (str[0] == '1') flags = JIT_F_OPT_1;
437 else if (str[0] == '2') flags = JIT_F_OPT_2;
438 else flags = JIT_F_OPT_3;
439 J->flags = (J->flags & ~JIT_F_OPT_MASK) | flags;
440 return 1; /* Ok. */
442 return 0; /* No match. */
445 /* Parse optimization flag. */
446 static int jitopt_flag(jit_State *J, const char *str)
448 const char *lst = JIT_F_OPTSTRING;
449 uint32_t opt;
450 int set = 1;
451 if (str[0] == '+') {
452 str++;
453 } else if (str[0] == '-') {
454 str++;
455 set = 0;
456 } else if (str[0] == 'n' && str[1] == 'o') {
457 str += str[2] == '-' ? 3 : 2;
458 set = 0;
460 for (opt = JIT_F_OPT; ; opt <<= 1) {
461 size_t len = *(const uint8_t *)lst;
462 if (len == 0)
463 break;
464 if (strncmp(str, lst+1, len) == 0 && str[len] == '\0') {
465 if (set) J->flags |= opt; else J->flags &= ~opt;
466 return 1; /* Ok. */
468 lst += 1+len;
470 return 0; /* No match. */
473 /* Parse optimization parameter. */
474 static int jitopt_param(jit_State *J, const char *str)
476 const char *lst = JIT_P_STRING;
477 int i;
478 for (i = 0; i < JIT_P__MAX; i++) {
479 size_t len = *(const uint8_t *)lst;
480 lj_assertJ(len != 0, "bad JIT_P_STRING");
481 if (strncmp(str, lst+1, len) == 0 && str[len] == '=') {
482 int32_t n = 0;
483 const char *p = &str[len+1];
484 while (*p >= '0' && *p <= '9')
485 n = n*10 + (*p++ - '0');
486 if (*p) return 0; /* Malformed number. */
487 J->param[i] = n;
488 if (i == JIT_P_hotloop)
489 lj_dispatch_init_hotcount(J2G(J));
490 return 1; /* Ok. */
492 lst += 1+len;
494 return 0; /* No match. */
497 /* jit.opt.start(flags...) */
498 LJLIB_CF(jit_opt_start)
500 jit_State *J = L2J(L);
501 int nargs = (int)(L->top - L->base);
502 if (nargs == 0) {
503 J->flags = (J->flags & ~JIT_F_OPT_MASK) | JIT_F_OPT_DEFAULT;
504 } else {
505 int i;
506 for (i = 1; i <= nargs; i++) {
507 const char *str = strdata(lj_lib_checkstr(L, i));
508 if (!jitopt_level(J, str) &&
509 !jitopt_flag(J, str) &&
510 !jitopt_param(J, str))
511 lj_err_callerv(L, LJ_ERR_JITOPT, str);
514 return 0;
517 #include "lj_libdef.h"
519 #endif
521 /* -- jit.profile module -------------------------------------------------- */
523 #if LJ_HASPROFILE
525 #define LJLIB_MODULE_jit_profile
527 /* Not loaded by default, use: local profile = require("jit.profile") */
529 #define KEY_PROFILE_THREAD (U64x(80000000,00000000)|'t')
530 #define KEY_PROFILE_FUNC (U64x(80000000,00000000)|'f')
532 static void jit_profile_callback(lua_State *L2, lua_State *L, int samples,
533 int vmstate)
535 TValue key;
536 cTValue *tv;
537 key.u64 = KEY_PROFILE_FUNC;
538 tv = lj_tab_get(L, tabV(registry(L)), &key);
539 if (tvisfunc(tv)) {
540 char vmst = (char)vmstate;
541 int status;
542 setfuncV(L2, L2->top++, funcV(tv));
543 setthreadV(L2, L2->top++, L);
544 setintV(L2->top++, samples);
545 setstrV(L2, L2->top++, lj_str_new(L2, &vmst, 1));
546 status = lua_pcall(L2, 3, 0, 0); /* callback(thread, samples, vmstate) */
547 if (status) {
548 if (G(L2)->panic) G(L2)->panic(L2);
549 exit(EXIT_FAILURE);
551 lj_trace_abort(G(L2));
555 /* profile.start(mode, cb) */
556 LJLIB_CF(jit_profile_start)
558 GCtab *registry = tabV(registry(L));
559 GCstr *mode = lj_lib_optstr(L, 1);
560 GCfunc *func = lj_lib_checkfunc(L, 2);
561 lua_State *L2 = lua_newthread(L); /* Thread that runs profiler callback. */
562 TValue key;
563 /* Anchor thread and function in registry. */
564 key.u64 = KEY_PROFILE_THREAD;
565 setthreadV(L, lj_tab_set(L, registry, &key), L2);
566 key.u64 = KEY_PROFILE_FUNC;
567 setfuncV(L, lj_tab_set(L, registry, &key), func);
568 lj_gc_anybarriert(L, registry);
569 luaJIT_profile_start(L, mode ? strdata(mode) : "",
570 (luaJIT_profile_callback)jit_profile_callback, L2);
571 return 0;
574 /* profile.stop() */
575 LJLIB_CF(jit_profile_stop)
577 GCtab *registry;
578 TValue key;
579 luaJIT_profile_stop(L);
580 registry = tabV(registry(L));
581 key.u64 = KEY_PROFILE_THREAD;
582 setnilV(lj_tab_set(L, registry, &key));
583 key.u64 = KEY_PROFILE_FUNC;
584 setnilV(lj_tab_set(L, registry, &key));
585 lj_gc_anybarriert(L, registry);
586 return 0;
589 /* dump = profile.dumpstack([thread,] fmt, depth) */
590 LJLIB_CF(jit_profile_dumpstack)
592 lua_State *L2 = L;
593 int arg = 0;
594 size_t len;
595 int depth;
596 GCstr *fmt;
597 const char *p;
598 if (L->top > L->base && tvisthread(L->base)) {
599 L2 = threadV(L->base);
600 arg = 1;
602 fmt = lj_lib_checkstr(L, arg+1);
603 depth = lj_lib_checkint(L, arg+2);
604 p = luaJIT_profile_dumpstack(L2, strdata(fmt), depth, &len);
605 lua_pushlstring(L, p, len);
606 return 1;
609 #include "lj_libdef.h"
611 static int luaopen_jit_profile(lua_State *L)
613 LJ_LIB_REG(L, NULL, jit_profile);
614 return 1;
617 #endif
619 /* -- JIT compiler initialization ----------------------------------------- */
621 #if LJ_HASJIT
622 /* Default values for JIT parameters. */
623 static const int32_t jit_param_default[JIT_P__MAX+1] = {
624 #define JIT_PARAMINIT(len, name, value) (value),
625 JIT_PARAMDEF(JIT_PARAMINIT)
626 #undef JIT_PARAMINIT
630 #if LJ_TARGET_ARM && LJ_TARGET_LINUX
631 #include <sys/utsname.h>
632 #endif
634 /* Arch-dependent CPU feature detection. */
635 static uint32_t jit_cpudetect(void)
637 uint32_t flags = 0;
638 #if LJ_TARGET_X86ORX64
640 uint32_t vendor[4];
641 uint32_t features[4];
642 if (lj_vm_cpuid(0, vendor) && lj_vm_cpuid(1, features)) {
643 flags |= ((features[2] >> 0)&1) * JIT_F_SSE3;
644 flags |= ((features[2] >> 19)&1) * JIT_F_SSE4_1;
645 if (vendor[0] >= 7) {
646 uint32_t xfeatures[4];
647 lj_vm_cpuid(7, xfeatures);
648 flags |= ((xfeatures[1] >> 8)&1) * JIT_F_BMI2;
651 /* Don't bother checking for SSE2 -- the VM will crash before getting here. */
653 #elif LJ_TARGET_ARM
655 int ver = LJ_ARCH_VERSION; /* Compile-time ARM CPU detection. */
656 #if LJ_TARGET_LINUX
657 if (ver < 70) { /* Runtime ARM CPU detection. */
658 struct utsname ut;
659 uname(&ut);
660 if (strncmp(ut.machine, "armv", 4) == 0) {
661 if (ut.machine[4] >= '8') ver = 80;
662 else if (ut.machine[4] == '7') ver = 70;
663 else if (ut.machine[4] == '6') ver = 60;
666 #endif
667 flags |= ver >= 70 ? JIT_F_ARMV7 :
668 ver >= 61 ? JIT_F_ARMV6T2_ :
669 ver >= 60 ? JIT_F_ARMV6_ : 0;
670 flags |= LJ_ARCH_HASFPU == 0 ? 0 : ver >= 70 ? JIT_F_VFPV3 : JIT_F_VFPV2;
672 #elif LJ_TARGET_ARM64
674 /* No optional CPU features to detect (for now). */
676 #elif LJ_TARGET_PPC
678 #if LJ_ARCH_SQRT
679 flags |= JIT_F_SQRT;
680 #endif
681 #if LJ_ARCH_ROUND
682 flags |= JIT_F_ROUND;
683 #endif
685 #elif LJ_TARGET_MIPS
687 /* Compile-time MIPS CPU detection. */
688 #if LJ_ARCH_VERSION >= 20
689 flags |= JIT_F_MIPSXXR2;
690 #endif
691 /* Runtime MIPS CPU detection. */
692 #if defined(__GNUC__)
693 if (!(flags & JIT_F_MIPSXXR2)) {
694 int x;
695 #ifdef __mips16
696 x = 0; /* Runtime detection is difficult. Ensure optimal -march flags. */
697 #else
698 /* On MIPS32R1 rotr is treated as srl. rotr r2,r2,1 -> srl r2,r2,1. */
699 __asm__("li $2, 1\n\t.long 0x00221042\n\tmove %0, $2" : "=r"(x) : : "$2");
700 #endif
701 if (x) flags |= JIT_F_MIPSXXR2; /* Either 0x80000000 (R2) or 0 (R1). */
703 #endif
705 #else
706 #error "Missing CPU detection for this architecture"
707 #endif
708 return flags;
711 /* Initialize JIT compiler. */
712 static void jit_init(lua_State *L)
714 jit_State *J = L2J(L);
715 J->flags = jit_cpudetect() | JIT_F_ON | JIT_F_OPT_DEFAULT;
716 memcpy(J->param, jit_param_default, sizeof(J->param));
717 lj_dispatch_update(G(L));
719 #endif
721 LUALIB_API int luaopen_jit(lua_State *L)
723 #if LJ_HASJIT
724 jit_init(L);
725 #endif
726 lua_pushliteral(L, LJ_OS_NAME);
727 lua_pushliteral(L, LJ_ARCH_NAME);
728 lua_pushinteger(L, LUAJIT_VERSION_NUM); /* Deprecated. */
729 lua_pushliteral(L, LUAJIT_VERSION);
730 LJ_LIB_REG(L, LUA_JITLIBNAME, jit);
731 #if LJ_HASPROFILE
732 lj_lib_prereg(L, LUA_JITLIBNAME ".profile", luaopen_jit_profile,
733 tabref(L->env));
734 #endif
735 #ifndef LUAJIT_DISABLE_JITUTIL
736 lj_lib_prereg(L, LUA_JITLIBNAME ".util", luaopen_jit_util, tabref(L->env));
737 #endif
738 #if LJ_HASJIT
739 LJ_LIB_REG(L, "jit.opt", jit_opt);
740 #endif
741 L->top -= 2;
742 return 1;