diff options
Diffstat (limited to 'src/lib_jit.c')
| -rw-r--r-- | src/lib_jit.c | 284 |
1 files changed, 191 insertions, 93 deletions
diff --git a/src/lib_jit.c b/src/lib_jit.c index db66b819..a7c553ab 100644 --- a/src/lib_jit.c +++ b/src/lib_jit.c | |||
| @@ -10,13 +10,17 @@ | |||
| 10 | #include "lauxlib.h" | 10 | #include "lauxlib.h" |
| 11 | #include "lualib.h" | 11 | #include "lualib.h" |
| 12 | 12 | ||
| 13 | #include "lj_arch.h" | ||
| 14 | #include "lj_obj.h" | 13 | #include "lj_obj.h" |
| 14 | #include "lj_gc.h" | ||
| 15 | #include "lj_err.h" | 15 | #include "lj_err.h" |
| 16 | #include "lj_debug.h" | 16 | #include "lj_debug.h" |
| 17 | #include "lj_str.h" | 17 | #include "lj_str.h" |
| 18 | #include "lj_tab.h" | 18 | #include "lj_tab.h" |
| 19 | #include "lj_state.h" | ||
| 19 | #include "lj_bc.h" | 20 | #include "lj_bc.h" |
| 21 | #if LJ_HASFFI | ||
| 22 | #include "lj_ctype.h" | ||
| 23 | #endif | ||
| 20 | #if LJ_HASJIT | 24 | #if LJ_HASJIT |
| 21 | #include "lj_ir.h" | 25 | #include "lj_ir.h" |
| 22 | #include "lj_jit.h" | 26 | #include "lj_jit.h" |
| @@ -24,6 +28,7 @@ | |||
| 24 | #include "lj_iropt.h" | 28 | #include "lj_iropt.h" |
| 25 | #include "lj_target.h" | 29 | #include "lj_target.h" |
| 26 | #endif | 30 | #endif |
| 31 | #include "lj_trace.h" | ||
| 27 | #include "lj_dispatch.h" | 32 | #include "lj_dispatch.h" |
| 28 | #include "lj_vm.h" | 33 | #include "lj_vm.h" |
| 29 | #include "lj_vmevent.h" | 34 | #include "lj_vmevent.h" |
| @@ -99,8 +104,8 @@ LJLIB_CF(jit_status) | |||
| 99 | jit_State *J = L2J(L); | 104 | jit_State *J = L2J(L); |
| 100 | L->top = L->base; | 105 | L->top = L->base; |
| 101 | setboolV(L->top++, (J->flags & JIT_F_ON) ? 1 : 0); | 106 | setboolV(L->top++, (J->flags & JIT_F_ON) ? 1 : 0); |
| 102 | flagbits_to_strings(L, J->flags, JIT_F_CPU_FIRST, JIT_F_CPUSTRING); | 107 | flagbits_to_strings(L, J->flags, JIT_F_CPU, JIT_F_CPUSTRING); |
| 103 | flagbits_to_strings(L, J->flags, JIT_F_OPT_FIRST, JIT_F_OPTSTRING); | 108 | flagbits_to_strings(L, J->flags, JIT_F_OPT, JIT_F_OPTSTRING); |
| 104 | return (int)(L->top - L->base); | 109 | return (int)(L->top - L->base); |
| 105 | #else | 110 | #else |
| 106 | setboolV(L->top++, 0); | 111 | setboolV(L->top++, 0); |
| @@ -108,6 +113,13 @@ LJLIB_CF(jit_status) | |||
| 108 | #endif | 113 | #endif |
| 109 | } | 114 | } |
| 110 | 115 | ||
| 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 | |||
| 111 | LJLIB_CF(jit_attach) | 123 | LJLIB_CF(jit_attach) |
| 112 | { | 124 | { |
| 113 | #ifdef LUAJIT_DISABLE_VMEVENT | 125 | #ifdef LUAJIT_DISABLE_VMEVENT |
| @@ -149,24 +161,6 @@ LJLIB_PUSH(top-2) LJLIB_SET(version) | |||
| 149 | 161 | ||
| 150 | /* -- Reflection API for Lua functions ------------------------------------ */ | 162 | /* -- Reflection API for Lua functions ------------------------------------ */ |
| 151 | 163 | ||
| 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 | |||
| 170 | static void setintfield(lua_State *L, GCtab *t, const char *name, int32_t val) | 164 | static void setintfield(lua_State *L, GCtab *t, const char *name, int32_t val) |
| 171 | { | 165 | { |
| 172 | setintV(lj_tab_setstr(L, t, lj_str_newz(L, name)), val); | 166 | setintV(lj_tab_setstr(L, t, lj_str_newz(L, name)), val); |
| @@ -175,7 +169,7 @@ static void setintfield(lua_State *L, GCtab *t, const char *name, int32_t val) | |||
| 175 | /* local info = jit.util.funcinfo(func [,pc]) */ | 169 | /* local info = jit.util.funcinfo(func [,pc]) */ |
| 176 | LJLIB_CF(jit_util_funcinfo) | 170 | LJLIB_CF(jit_util_funcinfo) |
| 177 | { | 171 | { |
| 178 | GCproto *pt = check_Lproto(L, 1); | 172 | GCproto *pt = lj_lib_checkLproto(L, 1, 1); |
| 179 | if (pt) { | 173 | if (pt) { |
| 180 | BCPos pc = (BCPos)lj_lib_optint(L, 2, 0); | 174 | BCPos pc = (BCPos)lj_lib_optint(L, 2, 0); |
| 181 | GCtab *t; | 175 | GCtab *t; |
| @@ -217,12 +211,12 @@ LJLIB_CF(jit_util_funcinfo) | |||
| 217 | /* local ins, m = jit.util.funcbc(func, pc) */ | 211 | /* local ins, m = jit.util.funcbc(func, pc) */ |
| 218 | LJLIB_CF(jit_util_funcbc) | 212 | LJLIB_CF(jit_util_funcbc) |
| 219 | { | 213 | { |
| 220 | GCproto *pt = check_Lproto(L, 0); | 214 | GCproto *pt = lj_lib_checkLproto(L, 1, 0); |
| 221 | BCPos pc = (BCPos)lj_lib_checkint(L, 2); | 215 | BCPos pc = (BCPos)lj_lib_checkint(L, 2); |
| 222 | if (pc < pt->sizebc) { | 216 | if (pc < pt->sizebc) { |
| 223 | BCIns ins = proto_bc(pt)[pc]; | 217 | BCIns ins = proto_bc(pt)[pc]; |
| 224 | BCOp op = bc_op(ins); | 218 | BCOp op = bc_op(ins); |
| 225 | lua_assert(op < BC__MAX); | 219 | lj_assertL(op < BC__MAX, "bad bytecode op %d", op); |
| 226 | setintV(L->top, ins); | 220 | setintV(L->top, ins); |
| 227 | setintV(L->top+1, lj_bc_mode[op]); | 221 | setintV(L->top+1, lj_bc_mode[op]); |
| 228 | L->top += 2; | 222 | L->top += 2; |
| @@ -234,7 +228,7 @@ LJLIB_CF(jit_util_funcbc) | |||
| 234 | /* local k = jit.util.funck(func, idx) */ | 228 | /* local k = jit.util.funck(func, idx) */ |
| 235 | LJLIB_CF(jit_util_funck) | 229 | LJLIB_CF(jit_util_funck) |
| 236 | { | 230 | { |
| 237 | GCproto *pt = check_Lproto(L, 0); | 231 | GCproto *pt = lj_lib_checkLproto(L, 1, 0); |
| 238 | ptrdiff_t idx = (ptrdiff_t)lj_lib_checkint(L, 2); | 232 | ptrdiff_t idx = (ptrdiff_t)lj_lib_checkint(L, 2); |
| 239 | if (idx >= 0) { | 233 | if (idx >= 0) { |
| 240 | if (idx < (ptrdiff_t)pt->sizekn) { | 234 | if (idx < (ptrdiff_t)pt->sizekn) { |
| @@ -254,7 +248,7 @@ LJLIB_CF(jit_util_funck) | |||
| 254 | /* local name = jit.util.funcuvname(func, idx) */ | 248 | /* local name = jit.util.funcuvname(func, idx) */ |
| 255 | LJLIB_CF(jit_util_funcuvname) | 249 | LJLIB_CF(jit_util_funcuvname) |
| 256 | { | 250 | { |
| 257 | GCproto *pt = check_Lproto(L, 0); | 251 | GCproto *pt = lj_lib_checkLproto(L, 1, 0); |
| 258 | uint32_t idx = (uint32_t)lj_lib_checkint(L, 2); | 252 | uint32_t idx = (uint32_t)lj_lib_checkint(L, 2); |
| 259 | if (idx < pt->sizeuv) { | 253 | if (idx < pt->sizeuv) { |
| 260 | setstrV(L, L->top-1, lj_str_newz(L, lj_debug_uvname(pt, idx))); | 254 | setstrV(L, L->top-1, lj_str_newz(L, lj_debug_uvname(pt, idx))); |
| @@ -280,7 +274,7 @@ static GCtrace *jit_checktrace(lua_State *L) | |||
| 280 | /* Names of link types. ORDER LJ_TRLINK */ | 274 | /* Names of link types. ORDER LJ_TRLINK */ |
| 281 | static const char *const jit_trlinkname[] = { | 275 | static const char *const jit_trlinkname[] = { |
| 282 | "none", "root", "loop", "tail-recursion", "up-recursion", "down-recursion", | 276 | "none", "root", "loop", "tail-recursion", "up-recursion", "down-recursion", |
| 283 | "interpreter", "return" | 277 | "interpreter", "return", "stitch" |
| 284 | }; | 278 | }; |
| 285 | 279 | ||
| 286 | /* local info = jit.util.traceinfo(tr) */ | 280 | /* local info = jit.util.traceinfo(tr) */ |
| @@ -333,6 +327,9 @@ LJLIB_CF(jit_util_tracek) | |||
| 333 | slot = ir->op2; | 327 | slot = ir->op2; |
| 334 | ir = &T->ir[ir->op1]; | 328 | ir = &T->ir[ir->op1]; |
| 335 | } | 329 | } |
| 330 | #if LJ_HASFFI | ||
| 331 | if (ir->o == IR_KINT64) ctype_loadffi(L); | ||
| 332 | #endif | ||
| 336 | lj_ir_kvalue(L, L->top-2, ir); | 333 | lj_ir_kvalue(L, L->top-2, ir); |
| 337 | setintV(L->top-1, (int32_t)irt_type(ir->t)); | 334 | setintV(L->top-1, (int32_t)irt_type(ir->t)); |
| 338 | if (slot == -1) | 335 | if (slot == -1) |
| @@ -407,7 +404,8 @@ LJLIB_CF(jit_util_ircalladdr) | |||
| 407 | { | 404 | { |
| 408 | uint32_t idx = (uint32_t)lj_lib_checkint(L, 1); | 405 | uint32_t idx = (uint32_t)lj_lib_checkint(L, 1); |
| 409 | if (idx < IRCALL__MAX) { | 406 | if (idx < IRCALL__MAX) { |
| 410 | setintptrV(L->top-1, (intptr_t)(void *)lj_ir_callinfo[idx].func); | 407 | ASMFunction func = lj_ir_callinfo[idx].func; |
| 408 | setintptrV(L->top-1, (intptr_t)(void *)lj_ptr_strip(func)); | ||
| 411 | return 1; | 409 | return 1; |
| 412 | } | 410 | } |
| 413 | return 0; | 411 | return 0; |
| @@ -417,6 +415,12 @@ LJLIB_CF(jit_util_ircalladdr) | |||
| 417 | 415 | ||
| 418 | #include "lj_libdef.h" | 416 | #include "lj_libdef.h" |
| 419 | 417 | ||
| 418 | static int luaopen_jit_util(lua_State *L) | ||
| 419 | { | ||
| 420 | LJ_LIB_REG(L, NULL, jit_util); | ||
| 421 | return 1; | ||
| 422 | } | ||
| 423 | |||
| 420 | /* -- jit.opt module ------------------------------------------------------ */ | 424 | /* -- jit.opt module ------------------------------------------------------ */ |
| 421 | 425 | ||
| 422 | #if LJ_HASJIT | 426 | #if LJ_HASJIT |
| @@ -453,7 +457,7 @@ static int jitopt_flag(jit_State *J, const char *str) | |||
| 453 | str += str[2] == '-' ? 3 : 2; | 457 | str += str[2] == '-' ? 3 : 2; |
| 454 | set = 0; | 458 | set = 0; |
| 455 | } | 459 | } |
| 456 | for (opt = JIT_F_OPT_FIRST; ; opt <<= 1) { | 460 | for (opt = JIT_F_OPT; ; opt <<= 1) { |
| 457 | size_t len = *(const uint8_t *)lst; | 461 | size_t len = *(const uint8_t *)lst; |
| 458 | if (len == 0) | 462 | if (len == 0) |
| 459 | break; | 463 | break; |
| @@ -473,14 +477,23 @@ static int jitopt_param(jit_State *J, const char *str) | |||
| 473 | int i; | 477 | int i; |
| 474 | for (i = 0; i < JIT_P__MAX; i++) { | 478 | for (i = 0; i < JIT_P__MAX; i++) { |
| 475 | size_t len = *(const uint8_t *)lst; | 479 | size_t len = *(const uint8_t *)lst; |
| 476 | lua_assert(len != 0); | 480 | lj_assertJ(len != 0, "bad JIT_P_STRING"); |
| 477 | if (strncmp(str, lst+1, len) == 0 && str[len] == '=') { | 481 | if (strncmp(str, lst+1, len) == 0 && str[len] == '=') { |
| 478 | int32_t n = 0; | 482 | uint32_t n = 0; |
| 479 | const char *p = &str[len+1]; | 483 | const char *p = &str[len+1]; |
| 480 | while (*p >= '0' && *p <= '9') | 484 | while (*p >= '0' && *p <= '9') |
| 481 | n = n*10 + (*p++ - '0'); | 485 | n = n*10 + (*p++ - '0'); |
| 482 | if (*p) return 0; /* Malformed number. */ | 486 | if (*p || (int32_t)n < 0) return 0; /* Malformed number. */ |
| 483 | J->param[i] = n; | 487 | if (i == JIT_P_sizemcode) { /* Adjust to required range here. */ |
| 488 | #if LJ_TARGET_JUMPRANGE | ||
| 489 | uint32_t maxkb = ((1 << (LJ_TARGET_JUMPRANGE - 10)) - 64); | ||
| 490 | #else | ||
| 491 | uint32_t maxkb = ((1 << (31 - 10)) - 64); | ||
| 492 | #endif | ||
| 493 | n = (n + (LJ_PAGESIZE >> 10) - 1) & ~((LJ_PAGESIZE >> 10) - 1); | ||
| 494 | if (n > maxkb) n = maxkb; | ||
| 495 | } | ||
| 496 | J->param[i] = (int32_t)n; | ||
| 484 | if (i == JIT_P_hotloop) | 497 | if (i == JIT_P_hotloop) |
| 485 | lj_dispatch_init_hotcount(J2G(J)); | 498 | lj_dispatch_init_hotcount(J2G(J)); |
| 486 | return 1; /* Ok. */ | 499 | return 1; /* Ok. */ |
| @@ -514,6 +527,104 @@ LJLIB_CF(jit_opt_start) | |||
| 514 | 527 | ||
| 515 | #endif | 528 | #endif |
| 516 | 529 | ||
| 530 | /* -- jit.profile module -------------------------------------------------- */ | ||
| 531 | |||
| 532 | #if LJ_HASPROFILE | ||
| 533 | |||
| 534 | #define LJLIB_MODULE_jit_profile | ||
| 535 | |||
| 536 | /* Not loaded by default, use: local profile = require("jit.profile") */ | ||
| 537 | |||
| 538 | #define KEY_PROFILE_THREAD (U64x(81000000,00000000)|'t') | ||
| 539 | #define KEY_PROFILE_FUNC (U64x(81000000,00000000)|'f') | ||
| 540 | |||
| 541 | static void jit_profile_callback(lua_State *L2, lua_State *L, int samples, | ||
| 542 | int vmstate) | ||
| 543 | { | ||
| 544 | TValue key; | ||
| 545 | cTValue *tv; | ||
| 546 | key.u64 = KEY_PROFILE_FUNC; | ||
| 547 | tv = lj_tab_get(L, tabV(registry(L)), &key); | ||
| 548 | if (tvisfunc(tv)) { | ||
| 549 | char vmst = (char)vmstate; | ||
| 550 | int status; | ||
| 551 | setfuncV(L2, L2->top++, funcV(tv)); | ||
| 552 | setthreadV(L2, L2->top++, L); | ||
| 553 | setintV(L2->top++, samples); | ||
| 554 | setstrV(L2, L2->top++, lj_str_new(L2, &vmst, 1)); | ||
| 555 | status = lua_pcall(L2, 3, 0, 0); /* callback(thread, samples, vmstate) */ | ||
| 556 | if (status) { | ||
| 557 | if (G(L2)->panic) G(L2)->panic(L2); | ||
| 558 | exit(EXIT_FAILURE); | ||
| 559 | } | ||
| 560 | lj_trace_abort(G(L2)); | ||
| 561 | } | ||
| 562 | } | ||
| 563 | |||
| 564 | /* profile.start(mode, cb) */ | ||
| 565 | LJLIB_CF(jit_profile_start) | ||
| 566 | { | ||
| 567 | GCtab *registry = tabV(registry(L)); | ||
| 568 | GCstr *mode = lj_lib_optstr(L, 1); | ||
| 569 | GCfunc *func = lj_lib_checkfunc(L, 2); | ||
| 570 | lua_State *L2 = lua_newthread(L); /* Thread that runs profiler callback. */ | ||
| 571 | TValue key; | ||
| 572 | /* Anchor thread and function in registry. */ | ||
| 573 | key.u64 = KEY_PROFILE_THREAD; | ||
| 574 | setthreadV(L, lj_tab_set(L, registry, &key), L2); | ||
| 575 | key.u64 = KEY_PROFILE_FUNC; | ||
| 576 | setfuncV(L, lj_tab_set(L, registry, &key), func); | ||
| 577 | lj_gc_anybarriert(L, registry); | ||
| 578 | luaJIT_profile_start(L, mode ? strdata(mode) : "", | ||
| 579 | (luaJIT_profile_callback)jit_profile_callback, L2); | ||
| 580 | return 0; | ||
| 581 | } | ||
| 582 | |||
| 583 | /* profile.stop() */ | ||
| 584 | LJLIB_CF(jit_profile_stop) | ||
| 585 | { | ||
| 586 | GCtab *registry; | ||
| 587 | TValue key; | ||
| 588 | luaJIT_profile_stop(L); | ||
| 589 | registry = tabV(registry(L)); | ||
| 590 | key.u64 = KEY_PROFILE_THREAD; | ||
| 591 | setnilV(lj_tab_set(L, registry, &key)); | ||
| 592 | key.u64 = KEY_PROFILE_FUNC; | ||
| 593 | setnilV(lj_tab_set(L, registry, &key)); | ||
| 594 | lj_gc_anybarriert(L, registry); | ||
| 595 | return 0; | ||
| 596 | } | ||
| 597 | |||
| 598 | /* dump = profile.dumpstack([thread,] fmt, depth) */ | ||
| 599 | LJLIB_CF(jit_profile_dumpstack) | ||
| 600 | { | ||
| 601 | lua_State *L2 = L; | ||
| 602 | int arg = 0; | ||
| 603 | size_t len; | ||
| 604 | int depth; | ||
| 605 | GCstr *fmt; | ||
| 606 | const char *p; | ||
| 607 | if (L->top > L->base && tvisthread(L->base)) { | ||
| 608 | L2 = threadV(L->base); | ||
| 609 | arg = 1; | ||
| 610 | } | ||
| 611 | fmt = lj_lib_checkstr(L, arg+1); | ||
| 612 | depth = lj_lib_checkint(L, arg+2); | ||
| 613 | p = luaJIT_profile_dumpstack(L2, strdata(fmt), depth, &len); | ||
| 614 | lua_pushlstring(L, p, len); | ||
| 615 | return 1; | ||
| 616 | } | ||
| 617 | |||
| 618 | #include "lj_libdef.h" | ||
| 619 | |||
| 620 | static int luaopen_jit_profile(lua_State *L) | ||
| 621 | { | ||
| 622 | LJ_LIB_REG(L, NULL, jit_profile); | ||
| 623 | return 1; | ||
| 624 | } | ||
| 625 | |||
| 626 | #endif | ||
| 627 | |||
| 517 | /* -- JIT compiler initialization ----------------------------------------- */ | 628 | /* -- JIT compiler initialization ----------------------------------------- */ |
| 518 | 629 | ||
| 519 | #if LJ_HASJIT | 630 | #if LJ_HASJIT |
| @@ -524,66 +635,41 @@ JIT_PARAMDEF(JIT_PARAMINIT) | |||
| 524 | #undef JIT_PARAMINIT | 635 | #undef JIT_PARAMINIT |
| 525 | 0 | 636 | 0 |
| 526 | }; | 637 | }; |
| 527 | #endif | ||
| 528 | 638 | ||
| 529 | #if LJ_TARGET_ARM && LJ_TARGET_LINUX | 639 | #if LJ_TARGET_ARM && LJ_TARGET_LINUX |
| 530 | #include <sys/utsname.h> | 640 | #include <sys/utsname.h> |
| 531 | #endif | 641 | #endif |
| 532 | 642 | ||
| 533 | /* Arch-dependent CPU detection. */ | 643 | /* Arch-dependent CPU feature detection. */ |
| 534 | static uint32_t jit_cpudetect(lua_State *L) | 644 | static uint32_t jit_cpudetect(void) |
| 535 | { | 645 | { |
| 536 | uint32_t flags = 0; | 646 | uint32_t flags = 0; |
| 537 | #if LJ_TARGET_X86ORX64 | 647 | #if LJ_TARGET_X86ORX64 |
| 648 | |||
| 538 | uint32_t vendor[4]; | 649 | uint32_t vendor[4]; |
| 539 | uint32_t features[4]; | 650 | uint32_t features[4]; |
| 540 | if (lj_vm_cpuid(0, vendor) && lj_vm_cpuid(1, features)) { | 651 | 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; | 652 | flags |= ((features[2] >> 0)&1) * JIT_F_SSE3; |
| 549 | flags |= ((features[2] >> 19)&1) * JIT_F_SSE4_1; | 653 | flags |= ((features[2] >> 19)&1) * JIT_F_SSE4_1; |
| 550 | if (vendor[2] == 0x6c65746e) { /* Intel. */ | 654 | if (vendor[0] >= 7) { |
| 551 | if ((features[0] & 0x0ff00f00) == 0x00000f00) /* P4. */ | 655 | uint32_t xfeatures[4]; |
| 552 | flags |= JIT_F_P4; /* Currently unused. */ | 656 | lj_vm_cpuid(7, xfeatures); |
| 553 | else if ((features[0] & 0x0fff0ff0) == 0x000106c0) /* Atom. */ | 657 | flags |= ((xfeatures[1] >> 8)&1) * JIT_F_BMI2; |
| 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 | } | 658 | } |
| 562 | #endif | ||
| 563 | } | 659 | } |
| 564 | /* Check for required instruction set support on x86 (unnecessary on x64). */ | 660 | /* Don't bother checking for SSE2 -- the VM will crash before getting here. */ |
| 565 | #if LJ_TARGET_X86 | 661 | |
| 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 | 662 | #elif LJ_TARGET_ARM |
| 576 | #if LJ_HASJIT | 663 | |
| 577 | int ver = LJ_ARCH_VERSION; /* Compile-time ARM CPU detection. */ | 664 | int ver = LJ_ARCH_VERSION; /* Compile-time ARM CPU detection. */ |
| 578 | #if LJ_TARGET_LINUX | 665 | #if LJ_TARGET_LINUX |
| 579 | if (ver < 70) { /* Runtime ARM CPU detection. */ | 666 | if (ver < 70) { /* Runtime ARM CPU detection. */ |
| 580 | struct utsname ut; | 667 | struct utsname ut; |
| 581 | uname(&ut); | 668 | uname(&ut); |
| 582 | if (strncmp(ut.machine, "armv", 4) == 0) { | 669 | if (strncmp(ut.machine, "armv", 4) == 0) { |
| 583 | if (ut.machine[4] >= '7') | 670 | if (ut.machine[4] >= '8') ver = 80; |
| 584 | ver = 70; | 671 | else if (ut.machine[4] == '7') ver = 70; |
| 585 | else if (ut.machine[4] == '6') | 672 | else if (ut.machine[4] == '6') ver = 60; |
| 586 | ver = 60; | ||
| 587 | } | 673 | } |
| 588 | } | 674 | } |
| 589 | #endif | 675 | #endif |
| @@ -591,74 +677,86 @@ static uint32_t jit_cpudetect(lua_State *L) | |||
| 591 | ver >= 61 ? JIT_F_ARMV6T2_ : | 677 | ver >= 61 ? JIT_F_ARMV6T2_ : |
| 592 | ver >= 60 ? JIT_F_ARMV6_ : 0; | 678 | ver >= 60 ? JIT_F_ARMV6_ : 0; |
| 593 | flags |= LJ_ARCH_HASFPU == 0 ? 0 : ver >= 70 ? JIT_F_VFPV3 : JIT_F_VFPV2; | 679 | flags |= LJ_ARCH_HASFPU == 0 ? 0 : ver >= 70 ? JIT_F_VFPV3 : JIT_F_VFPV2; |
| 594 | #endif | 680 | |
| 681 | #elif LJ_TARGET_ARM64 | ||
| 682 | |||
| 683 | /* No optional CPU features to detect (for now). */ | ||
| 684 | |||
| 595 | #elif LJ_TARGET_PPC | 685 | #elif LJ_TARGET_PPC |
| 596 | #if LJ_HASJIT | 686 | |
| 597 | #if LJ_ARCH_SQRT | 687 | #if LJ_ARCH_SQRT |
| 598 | flags |= JIT_F_SQRT; | 688 | flags |= JIT_F_SQRT; |
| 599 | #endif | 689 | #endif |
| 600 | #if LJ_ARCH_ROUND | 690 | #if LJ_ARCH_ROUND |
| 601 | flags |= JIT_F_ROUND; | 691 | flags |= JIT_F_ROUND; |
| 602 | #endif | 692 | #endif |
| 603 | #endif | 693 | |
| 604 | #elif LJ_TARGET_PPCSPE | ||
| 605 | /* Nothing to do. */ | ||
| 606 | #elif LJ_TARGET_MIPS | 694 | #elif LJ_TARGET_MIPS |
| 607 | #if LJ_HASJIT | 695 | |
| 608 | /* Compile-time MIPS CPU detection. */ | 696 | /* Compile-time MIPS CPU detection. */ |
| 609 | #if LJ_ARCH_VERSION >= 20 | 697 | #if LJ_ARCH_VERSION >= 20 |
| 610 | flags |= JIT_F_MIPS32R2; | 698 | flags |= JIT_F_MIPSXXR2; |
| 611 | #endif | 699 | #endif |
| 612 | /* Runtime MIPS CPU detection. */ | 700 | /* Runtime MIPS CPU detection. */ |
| 613 | #if defined(__GNUC__) | 701 | #if defined(__GNUC__) |
| 614 | if (!(flags & JIT_F_MIPS32R2)) { | 702 | if (!(flags & JIT_F_MIPSXXR2)) { |
| 615 | int x; | 703 | int x; |
| 704 | #ifdef __mips16 | ||
| 705 | x = 0; /* Runtime detection is difficult. Ensure optimal -march flags. */ | ||
| 706 | #else | ||
| 616 | /* On MIPS32R1 rotr is treated as srl. rotr r2,r2,1 -> srl r2,r2,1. */ | 707 | /* 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"); | 708 | __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 | 709 | #endif |
| 710 | if (x) flags |= JIT_F_MIPSXXR2; /* Either 0x80000000 (R2) or 0 (R1). */ | ||
| 711 | } | ||
| 621 | #endif | 712 | #endif |
| 713 | |||
| 622 | #else | 714 | #else |
| 623 | #error "Missing CPU detection for this architecture" | 715 | #error "Missing CPU detection for this architecture" |
| 624 | #endif | 716 | #endif |
| 625 | UNUSED(L); | ||
| 626 | return flags; | 717 | return flags; |
| 627 | } | 718 | } |
| 628 | 719 | ||
| 629 | /* Initialize JIT compiler. */ | 720 | /* Initialize JIT compiler. */ |
| 630 | static void jit_init(lua_State *L) | 721 | static void jit_init(lua_State *L) |
| 631 | { | 722 | { |
| 632 | uint32_t flags = jit_cpudetect(L); | ||
| 633 | #if LJ_HASJIT | ||
| 634 | jit_State *J = L2J(L); | 723 | jit_State *J = L2J(L); |
| 635 | #if LJ_TARGET_X86 | 724 | J->flags = jit_cpudetect() | JIT_F_ON | JIT_F_OPT_DEFAULT; |
| 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)); | 725 | memcpy(J->param, jit_param_default, sizeof(J->param)); |
| 726 | #if LJ_TARGET_UNALIGNED | ||
| 727 | G(L)->tmptv.u64 = U64x(0000504d,4d500000); | ||
| 728 | #endif | ||
| 641 | lj_dispatch_update(G(L)); | 729 | lj_dispatch_update(G(L)); |
| 642 | #else | 730 | #if LJ_TARGET_UNALIGNED |
| 643 | UNUSED(flags); | 731 | /* If you get a crash below then your toolchain indicates unaligned |
| 732 | ** accesses are OK, but your kernel disagrees. I.e. fix your toolchain. | ||
| 733 | */ | ||
| 734 | if (*(uint32_t *)((char *)&G(L)->tmptv + 2) != 0x504d4d50u) L->top = NULL; | ||
| 644 | #endif | 735 | #endif |
| 645 | } | 736 | } |
| 737 | #endif | ||
| 646 | 738 | ||
| 647 | LUALIB_API int luaopen_jit(lua_State *L) | 739 | LUALIB_API int luaopen_jit(lua_State *L) |
| 648 | { | 740 | { |
| 741 | #if LJ_HASJIT | ||
| 742 | jit_init(L); | ||
| 743 | #endif | ||
| 649 | lua_pushliteral(L, LJ_OS_NAME); | 744 | lua_pushliteral(L, LJ_OS_NAME); |
| 650 | lua_pushliteral(L, LJ_ARCH_NAME); | 745 | lua_pushliteral(L, LJ_ARCH_NAME); |
| 651 | lua_pushinteger(L, LUAJIT_VERSION_NUM); /* Deprecated. */ | 746 | lua_pushinteger(L, LUAJIT_VERSION_NUM); /* Deprecated. */ |
| 652 | lua_pushliteral(L, LUAJIT_VERSION); | 747 | lua_pushliteral(L, LUAJIT_VERSION); |
| 653 | LJ_LIB_REG(L, LUA_JITLIBNAME, jit); | 748 | LJ_LIB_REG(L, LUA_JITLIBNAME, jit); |
| 749 | #if LJ_HASPROFILE | ||
| 750 | lj_lib_prereg(L, LUA_JITLIBNAME ".profile", luaopen_jit_profile, | ||
| 751 | tabref(L->env)); | ||
| 752 | #endif | ||
| 654 | #ifndef LUAJIT_DISABLE_JITUTIL | 753 | #ifndef LUAJIT_DISABLE_JITUTIL |
| 655 | LJ_LIB_REG(L, "jit.util", jit_util); | 754 | lj_lib_prereg(L, LUA_JITLIBNAME ".util", luaopen_jit_util, tabref(L->env)); |
| 656 | #endif | 755 | #endif |
| 657 | #if LJ_HASJIT | 756 | #if LJ_HASJIT |
| 658 | LJ_LIB_REG(L, "jit.opt", jit_opt); | 757 | LJ_LIB_REG(L, "jit.opt", jit_opt); |
| 659 | #endif | 758 | #endif |
| 660 | L->top -= 2; | 759 | L->top -= 2; |
| 661 | jit_init(L); | ||
| 662 | return 1; | 760 | return 1; |
| 663 | } | 761 | } |
| 664 | 762 | ||
