3 ** Copyright (C) 2005-2012 Mike Pall. See Copyright Notice in luajit.h
23 #include "lj_ircall.h"
25 #include "lj_target.h"
27 #include "lj_dispatch.h"
29 #include "lj_vmevent.h"
34 /* -- jit.* functions ----------------------------------------------------- */
36 #define LJLIB_MODULE_jit
38 static int setjitmode(lua_State
*L
, int mode
)
41 if (L
->base
== L
->top
|| tvisnil(L
->base
)) { /* jit.on/off/flush([nil]) */
42 mode
|= LUAJIT_MODE_ENGINE
;
44 /* jit.on/off/flush(func|proto, nil|true|false) */
45 if (tvisfunc(L
->base
) || tvisproto(L
->base
))
47 else if (!tvistrue(L
->base
)) /* jit.on/off/flush(true, nil|true|false) */
49 if (L
->base
+1 < L
->top
&& tvisbool(L
->base
+1))
50 mode
|= boolV(L
->base
+1) ? LUAJIT_MODE_ALLFUNC
: LUAJIT_MODE_ALLSUBFUNC
;
52 mode
|= LUAJIT_MODE_FUNC
;
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
);
58 lj_err_argt(L
, 1, LUA_TFUNCTION
);
65 return setjitmode(L
, LUAJIT_MODE_ON
);
70 return setjitmode(L
, LUAJIT_MODE_OFF
);
76 if (L
->base
< L
->top
&& !tvisnil(L
->base
)) {
77 int traceno
= lj_lib_checkint(L
, 1);
78 luaJIT_setmode(L
, traceno
, LUAJIT_MODE_FLUSH
|LUAJIT_MODE_TRACE
);
82 return setjitmode(L
, LUAJIT_MODE_FLUSH
);
86 /* Push a string for every flag bit that is set. */
87 static void flagbits_to_strings(lua_State
*L
, uint32_t flags
, uint32_t base
,
90 for (; *str
; base
<<= 1, str
+= 1+*str
)
92 setstrV(L
, L
->top
++, lj_str_new(L
, str
+1, *(uint8_t *)str
));
99 jit_State
*J
= L2J(L
);
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
);
106 setboolV(L
->top
++, 0);
113 #ifdef LUAJIT_DISABLE_VMEVENT
114 luaL_error(L
, "vmevent API disabled");
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
);
122 while (*p
) h
= h
^ (lj_rol(h
, 6) + *p
++);
124 lua_rawseti(L
, -2, VMEVENT_HASHIDX(h
));
125 G(L
)->vmevmask
= VMEVENT_NOCACHE
; /* Invalidate cache. */
126 } else { /* Detach if no event given. */
128 while (lua_next(L
, -2)) {
130 if (tvisfunc(L
->top
) && funcV(L
->top
) == fn
) {
131 setnilV(lj_tab_set(L
, tabV(L
->top
-2), L
->top
-1));
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
)
144 #include "lj_libdef.h"
146 /* -- jit.util.* functions ------------------------------------------------ */
148 #define LJLIB_MODULE_jit_util
150 /* -- Reflection API for Lua functions ------------------------------------ */
152 /* Return prototype of first argument (Lua function or prototype object) */
153 static GCproto
*check_Lproto(lua_State
*L
, int nolua
)
159 } else if (tvisfunc(o
)) {
160 if (isluafunc(funcV(o
)))
161 return funcproto(funcV(o
));
166 lj_err_argt(L
, 1, LUA_TFUNCTION
);
167 return NULL
; /* unreachable */
170 static void setintfield(lua_State
*L
, GCtab
*t
, const char *name
, int32_t val
)
172 setintV(lj_tab_setstr(L
, t
, lj_str_newz(L
, name
)), val
);
175 /* local info = jit.util.funcinfo(func [,pc]) */
176 LJLIB_CF(jit_util_funcinfo
)
178 GCproto
*pt
= check_Lproto(L
, 1);
180 BCPos pc
= (BCPos
)lj_lib_optint(L
, 2, 0);
182 lua_createtable(L
, 0, 16); /* Increment hash size if fields are added. */
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
);
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");
203 GCfunc
*fn
= funcV(L
->base
);
205 lua_createtable(L
, 0, 4); /* Increment hash size if fields are added. */
208 setintfield(L
, t
, "ffid", fn
->c
.ffid
);
209 setintptrV(lj_tab_setstr(L
, t
, lj_str_newlit(L
, "addr")),
210 (intptr_t)(void *)fn
->c
.f
);
211 setintfield(L
, t
, "upvalues", fn
->c
.nupvalues
);
216 /* local ins, m = jit.util.funcbc(func, pc) */
217 LJLIB_CF(jit_util_funcbc
)
219 GCproto
*pt
= check_Lproto(L
, 0);
220 BCPos pc
= (BCPos
)lj_lib_checkint(L
, 2);
221 if (pc
< pt
->sizebc
) {
222 BCIns ins
= proto_bc(pt
)[pc
];
223 BCOp op
= bc_op(ins
);
224 lua_assert(op
< BC__MAX
);
225 setintV(L
->top
, ins
);
226 setintV(L
->top
+1, lj_bc_mode
[op
]);
233 /* local k = jit.util.funck(func, idx) */
234 LJLIB_CF(jit_util_funck
)
236 GCproto
*pt
= check_Lproto(L
, 0);
237 ptrdiff_t idx
= (ptrdiff_t)lj_lib_checkint(L
, 2);
239 if (idx
< (ptrdiff_t)pt
->sizekn
) {
240 copyTV(L
, L
->top
-1, proto_knumtv(pt
, idx
));
244 if (~idx
< (ptrdiff_t)pt
->sizekgc
) {
245 GCobj
*gc
= proto_kgc(pt
, idx
);
246 setgcV(L
, L
->top
-1, gc
, ~gc
->gch
.gct
);
253 /* local name = jit.util.funcuvname(func, idx) */
254 LJLIB_CF(jit_util_funcuvname
)
256 GCproto
*pt
= check_Lproto(L
, 0);
257 uint32_t idx
= (uint32_t)lj_lib_checkint(L
, 2);
258 if (idx
< pt
->sizeuv
) {
259 setstrV(L
, L
->top
-1, lj_str_newz(L
, lj_debug_uvname(pt
, idx
)));
265 /* -- Reflection API for traces ------------------------------------------- */
269 /* Check trace argument. Must not throw for non-existent trace numbers. */
270 static GCtrace
*jit_checktrace(lua_State
*L
)
272 TraceNo tr
= (TraceNo
)lj_lib_checkint(L
, 1);
273 jit_State
*J
= L2J(L
);
274 if (tr
> 0 && tr
< J
->sizetrace
)
275 return traceref(J
, tr
);
279 /* Names of link types. ORDER LJ_TRLINK */
280 static const char *const jit_trlinkname
[] = {
281 "none", "root", "loop", "tail-recursion", "up-recursion", "down-recursion",
282 "interpreter", "return"
285 /* local info = jit.util.traceinfo(tr) */
286 LJLIB_CF(jit_util_traceinfo
)
288 GCtrace
*T
= jit_checktrace(L
);
291 lua_createtable(L
, 0, 8); /* Increment hash size if fields are added. */
293 setintfield(L
, t
, "nins", (int32_t)T
->nins
- REF_BIAS
- 1);
294 setintfield(L
, t
, "nk", REF_BIAS
- (int32_t)T
->nk
);
295 setintfield(L
, t
, "link", T
->link
);
296 setintfield(L
, t
, "nexit", T
->nsnap
);
297 setstrV(L
, L
->top
++, lj_str_newz(L
, jit_trlinkname
[T
->linktype
]));
298 lua_setfield(L
, -2, "linktype");
299 /* There are many more fields. Add them only when needed. */
305 /* local m, ot, op1, op2, prev = jit.util.traceir(tr, idx) */
306 LJLIB_CF(jit_util_traceir
)
308 GCtrace
*T
= jit_checktrace(L
);
309 IRRef ref
= (IRRef
)lj_lib_checkint(L
, 2) + REF_BIAS
;
310 if (T
&& ref
>= REF_BIAS
&& ref
< T
->nins
) {
311 IRIns
*ir
= &T
->ir
[ref
];
312 int32_t m
= lj_ir_mode
[ir
->o
];
313 setintV(L
->top
-2, m
);
314 setintV(L
->top
-1, ir
->ot
);
315 setintV(L
->top
++, (int32_t)ir
->op1
- (irm_op1(m
)==IRMref
? REF_BIAS
: 0));
316 setintV(L
->top
++, (int32_t)ir
->op2
- (irm_op2(m
)==IRMref
? REF_BIAS
: 0));
317 setintV(L
->top
++, ir
->prev
);
323 /* local k, t [, slot] = jit.util.tracek(tr, idx) */
324 LJLIB_CF(jit_util_tracek
)
326 GCtrace
*T
= jit_checktrace(L
);
327 IRRef ref
= (IRRef
)lj_lib_checkint(L
, 2) + REF_BIAS
;
328 if (T
&& ref
>= T
->nk
&& ref
< REF_BIAS
) {
329 IRIns
*ir
= &T
->ir
[ref
];
331 if (ir
->o
== IR_KSLOT
) {
333 ir
= &T
->ir
[ir
->op1
];
335 lj_ir_kvalue(L
, L
->top
-2, ir
);
336 setintV(L
->top
-1, (int32_t)irt_type(ir
->t
));
339 setintV(L
->top
++, slot
);
345 /* local snap = jit.util.tracesnap(tr, sn) */
346 LJLIB_CF(jit_util_tracesnap
)
348 GCtrace
*T
= jit_checktrace(L
);
349 SnapNo sn
= (SnapNo
)lj_lib_checkint(L
, 2);
350 if (T
&& sn
< T
->nsnap
) {
351 SnapShot
*snap
= &T
->snap
[sn
];
352 SnapEntry
*map
= &T
->snapmap
[snap
->mapofs
];
353 MSize n
, nent
= snap
->nent
;
355 lua_createtable(L
, nent
+2, 0);
357 setintV(lj_tab_setint(L
, t
, 0), (int32_t)snap
->ref
- REF_BIAS
);
358 setintV(lj_tab_setint(L
, t
, 1), (int32_t)snap
->nslots
);
359 for (n
= 0; n
< nent
; n
++)
360 setintV(lj_tab_setint(L
, t
, (int32_t)(n
+2)), (int32_t)map
[n
]);
361 setintV(lj_tab_setint(L
, t
, (int32_t)(nent
+2)), (int32_t)SNAP(255, 0, 0));
367 /* local mcode, addr, loop = jit.util.tracemc(tr) */
368 LJLIB_CF(jit_util_tracemc
)
370 GCtrace
*T
= jit_checktrace(L
);
371 if (T
&& T
->mcode
!= NULL
) {
372 setstrV(L
, L
->top
-1, lj_str_new(L
, (const char *)T
->mcode
, T
->szmcode
));
373 setintptrV(L
->top
++, (intptr_t)(void *)T
->mcode
);
374 setintV(L
->top
++, T
->mcloop
);
380 /* local addr = jit.util.traceexitstub([tr,] exitno) */
381 LJLIB_CF(jit_util_traceexitstub
)
383 #ifdef EXITSTUBS_PER_GROUP
384 ExitNo exitno
= (ExitNo
)lj_lib_checkint(L
, 1);
385 jit_State
*J
= L2J(L
);
386 if (exitno
< EXITSTUBS_PER_GROUP
*LJ_MAX_EXITSTUBGR
) {
387 setintptrV(L
->top
-1, (intptr_t)(void *)exitstub_addr(J
, exitno
));
391 if (L
->top
> L
->base
+1) { /* Don't throw for one-argument variant. */
392 GCtrace
*T
= jit_checktrace(L
);
393 ExitNo exitno
= (ExitNo
)lj_lib_checkint(L
, 2);
394 ExitNo maxexit
= T
->root
? T
->nsnap
+1 : T
->nsnap
;
395 if (T
&& T
->mcode
!= NULL
&& exitno
< maxexit
) {
396 setintptrV(L
->top
-1, (intptr_t)(void *)exitstub_trace_addr(T
, exitno
));
404 /* local addr = jit.util.ircalladdr(idx) */
405 LJLIB_CF(jit_util_ircalladdr
)
407 uint32_t idx
= (uint32_t)lj_lib_checkint(L
, 1);
408 if (idx
< IRCALL__MAX
) {
409 setintptrV(L
->top
-1, (intptr_t)(void *)lj_ir_callinfo
[idx
].func
);
417 static int trace_nojit(lua_State
*L
)
422 #define lj_cf_jit_util_traceinfo trace_nojit
423 #define lj_cf_jit_util_traceir trace_nojit
424 #define lj_cf_jit_util_tracek trace_nojit
425 #define lj_cf_jit_util_tracesnap trace_nojit
426 #define lj_cf_jit_util_tracemc trace_nojit
427 #define lj_cf_jit_util_traceexitstub trace_nojit
428 #define lj_cf_jit_util_ircalladdr trace_nojit
432 #include "lj_libdef.h"
434 /* -- jit.opt module ------------------------------------------------------ */
436 #define LJLIB_MODULE_jit_opt
439 /* Parse optimization level. */
440 static int jitopt_level(jit_State
*J
, const char *str
)
442 if (str
[0] >= '0' && str
[0] <= '9' && str
[1] == '\0') {
444 if (str
[0] == '0') flags
= JIT_F_OPT_0
;
445 else if (str
[0] == '1') flags
= JIT_F_OPT_1
;
446 else if (str
[0] == '2') flags
= JIT_F_OPT_2
;
447 else flags
= JIT_F_OPT_3
;
448 J
->flags
= (J
->flags
& ~JIT_F_OPT_MASK
) | flags
;
451 return 0; /* No match. */
454 /* Parse optimization flag. */
455 static int jitopt_flag(jit_State
*J
, const char *str
)
457 const char *lst
= JIT_F_OPTSTRING
;
462 } else if (str
[0] == '-') {
465 } else if (str
[0] == 'n' && str
[1] == 'o') {
466 str
+= str
[2] == '-' ? 3 : 2;
469 for (opt
= JIT_F_OPT_FIRST
; ; opt
<<= 1) {
470 size_t len
= *(const uint8_t *)lst
;
473 if (strncmp(str
, lst
+1, len
) == 0 && str
[len
] == '\0') {
474 if (set
) J
->flags
|= opt
; else J
->flags
&= ~opt
;
479 return 0; /* No match. */
482 /* Parse optimization parameter. */
483 static int jitopt_param(jit_State
*J
, const char *str
)
485 const char *lst
= JIT_P_STRING
;
487 for (i
= 0; i
< JIT_P__MAX
; i
++) {
488 size_t len
= *(const uint8_t *)lst
;
489 lua_assert(len
!= 0);
490 if (strncmp(str
, lst
+1, len
) == 0 && str
[len
] == '=') {
492 const char *p
= &str
[len
+1];
493 while (*p
>= '0' && *p
<= '9')
494 n
= n
*10 + (*p
++ - '0');
495 if (*p
) return 0; /* Malformed number. */
497 if (i
== JIT_P_hotloop
)
498 lj_dispatch_init_hotcount(J2G(J
));
503 return 0; /* No match. */
507 /* jit.opt.start(flags...) */
508 LJLIB_CF(jit_opt_start
)
511 jit_State
*J
= L2J(L
);
512 int nargs
= (int)(L
->top
- L
->base
);
514 J
->flags
= (J
->flags
& ~JIT_F_OPT_MASK
) | JIT_F_OPT_DEFAULT
;
517 for (i
= 1; i
<= nargs
; i
++) {
518 const char *str
= strdata(lj_lib_checkstr(L
, i
));
519 if (!jitopt_level(J
, str
) &&
520 !jitopt_flag(J
, str
) &&
521 !jitopt_param(J
, str
))
522 lj_err_callerv(L
, LJ_ERR_JITOPT
, str
);
526 lj_err_caller(L
, LJ_ERR_NOJIT
);
531 #include "lj_libdef.h"
533 /* -- JIT compiler initialization ----------------------------------------- */
536 /* Default values for JIT parameters. */
537 static const int32_t jit_param_default
[JIT_P__MAX
+1] = {
538 #define JIT_PARAMINIT(len, name, value) (value),
539 JIT_PARAMDEF(JIT_PARAMINIT
)
545 #if LJ_TARGET_ARM && LJ_TARGET_LINUX
546 #include <sys/utsname.h>
549 /* Arch-dependent CPU detection. */
550 static uint32_t jit_cpudetect(lua_State
*L
)
553 #if LJ_TARGET_X86ORX64
555 uint32_t features
[4];
556 if (lj_vm_cpuid(0, vendor
) && lj_vm_cpuid(1, features
)) {
561 flags
|= ((features
[3] >> 15)&1) * JIT_F_CMOV
;
562 flags
|= ((features
[3] >> 26)&1) * JIT_F_SSE2
;
564 flags
|= ((features
[2] >> 0)&1) * JIT_F_SSE3
;
565 flags
|= ((features
[2] >> 19)&1) * JIT_F_SSE4_1
;
566 if (vendor
[2] == 0x6c65746e) { /* Intel. */
567 if ((features
[0] & 0x0ff00f00) == 0x00000f00) /* P4. */
568 flags
|= JIT_F_P4
; /* Currently unused. */
569 else if ((features
[0] & 0x0fff0ff0) == 0x000106c0) /* Atom. */
570 flags
|= JIT_F_LEA_AGU
;
571 } else if (vendor
[2] == 0x444d4163) { /* AMD. */
572 uint32_t fam
= (features
[0] & 0x0ff00f00);
573 if (fam
== 0x00000f00) /* K8. */
574 flags
|= JIT_F_SPLIT_XMM
;
575 if (fam
>= 0x00000f00) /* K8, K10. */
576 flags
|= JIT_F_PREFER_IMUL
;
580 /* Check for required instruction set support on x86 (unnecessary on x64). */
582 #if !defined(LUAJIT_CPU_NOCMOV)
583 if (!(flags
& JIT_F_CMOV
))
584 luaL_error(L
, "Ancient CPU lacks CMOV support (recompile with -DLUAJIT_CPU_NOCMOV)");
586 #if defined(LUAJIT_CPU_SSE2)
587 if (!(flags
& JIT_F_SSE2
))
588 luaL_error(L
, "CPU does not support SSE2 (recompile without -DLUAJIT_CPU_SSE2)");
593 /* Compile-time ARM CPU detection. */
594 #if __ARM_ARCH_7__ || __ARM_ARCH_7A__ || __ARM_ARCH_7R__
595 flags
|= JIT_F_ARMV6
|JIT_F_ARMV6T2
|JIT_F_ARMV7
;
596 #elif __ARM_ARCH_6T2__
597 flags
|= JIT_F_ARMV6
|JIT_F_ARMV6T2
;
598 #elif __ARM_ARCH_6__ || __ARM_ARCH_6J__ || __ARM_ARCH_6Z__ || __ARM_ARCH_6ZK__
599 flags
|= JIT_F_ARMV6
;
601 /* Runtime ARM CPU detection. */
603 if (!(flags
& JIT_F_ARMV7
)) {
606 if (strncmp(ut
.machine
, "armv", 4) == 0) {
607 if (ut
.machine
[4] >= '7')
608 flags
|= JIT_F_ARMV6
|JIT_F_ARMV6T2
|JIT_F_ARMV7
;
609 else if (ut
.machine
[4] == '6')
610 flags
|= JIT_F_ARMV6
;
615 #elif LJ_TARGET_PPC || LJ_TARGET_PPCSPE
619 /* Compile-time MIPS CPU detection. */
620 #if _MIPS_ARCH_MIPS32R2
621 flags
|= JIT_F_MIPS32R2
;
623 /* Runtime MIPS CPU detection. */
624 #if defined(__GNUC__)
625 if (!(flags
& JIT_F_MIPS32R2
)) {
627 /* On MIPS32R1 rotr is treated as srl. rotr r2,r2,1 -> srl r2,r2,1. */
628 __asm__("li $2, 1\n\t.long 0x00221042\n\tmove %0, $2" : "=r"(x
) : : "$2");
629 if (x
) flags
|= JIT_F_MIPS32R2
; /* Either 0x80000000 (R2) or 0 (R1). */
634 #error "Missing CPU detection for this architecture"
640 /* Initialize JIT compiler. */
641 static void jit_init(lua_State
*L
)
643 uint32_t flags
= jit_cpudetect(L
);
645 jit_State
*J
= L2J(L
);
647 /* Silently turn off the JIT compiler on CPUs without SSE2. */
648 if ((flags
& JIT_F_SSE2
))
650 J
->flags
= flags
| JIT_F_ON
| JIT_F_OPT_DEFAULT
;
651 memcpy(J
->param
, jit_param_default
, sizeof(J
->param
));
652 lj_dispatch_update(G(L
));
658 LUALIB_API
int luaopen_jit(lua_State
*L
)
660 lua_pushliteral(L
, LJ_OS_NAME
);
661 lua_pushliteral(L
, LJ_ARCH_NAME
);
662 lua_pushinteger(L
, LUAJIT_VERSION_NUM
);
663 lua_pushliteral(L
, LUAJIT_VERSION
);
664 LJ_LIB_REG(L
, LUA_JITLIBNAME
, jit
);
665 #ifndef LUAJIT_DISABLE_JITUTIL
666 LJ_LIB_REG(L
, "jit.util", jit_util
);
668 LJ_LIB_REG(L
, "jit.opt", jit_opt
);