diff options
Diffstat (limited to '')
-rw-r--r-- | src/lib_jit.c | 159 |
1 files changed, 134 insertions, 25 deletions
diff --git a/src/lib_jit.c b/src/lib_jit.c index 921b84c8..c6330c49 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" |
@@ -279,7 +284,7 @@ static GCtrace *jit_checktrace(lua_State *L) | |||
279 | /* Names of link types. ORDER LJ_TRLINK */ | 284 | /* Names of link types. ORDER LJ_TRLINK */ |
280 | static const char *const jit_trlinkname[] = { | 285 | static const char *const jit_trlinkname[] = { |
281 | "none", "root", "loop", "tail-recursion", "up-recursion", "down-recursion", | 286 | "none", "root", "loop", "tail-recursion", "up-recursion", "down-recursion", |
282 | "interpreter", "return" | 287 | "interpreter", "return", "stitch" |
283 | }; | 288 | }; |
284 | 289 | ||
285 | /* local info = jit.util.traceinfo(tr) */ | 290 | /* local info = jit.util.traceinfo(tr) */ |
@@ -332,6 +337,13 @@ LJLIB_CF(jit_util_tracek) | |||
332 | slot = ir->op2; | 337 | slot = ir->op2; |
333 | ir = &T->ir[ir->op1]; | 338 | ir = &T->ir[ir->op1]; |
334 | } | 339 | } |
340 | #if LJ_HASFFI | ||
341 | if (ir->o == IR_KINT64 && !ctype_ctsG(G(L))) { | ||
342 | ptrdiff_t oldtop = savestack(L, L->top); | ||
343 | luaopen_ffi(L); /* Load FFI library on-demand. */ | ||
344 | L->top = restorestack(L, oldtop); | ||
345 | } | ||
346 | #endif | ||
335 | lj_ir_kvalue(L, L->top-2, ir); | 347 | lj_ir_kvalue(L, L->top-2, ir); |
336 | setintV(L->top-1, (int32_t)irt_type(ir->t)); | 348 | setintV(L->top-1, (int32_t)irt_type(ir->t)); |
337 | if (slot == -1) | 349 | if (slot == -1) |
@@ -416,6 +428,12 @@ LJLIB_CF(jit_util_ircalladdr) | |||
416 | 428 | ||
417 | #include "lj_libdef.h" | 429 | #include "lj_libdef.h" |
418 | 430 | ||
431 | static int luaopen_jit_util(lua_State *L) | ||
432 | { | ||
433 | LJ_LIB_REG(L, NULL, jit_util); | ||
434 | return 1; | ||
435 | } | ||
436 | |||
419 | /* -- jit.opt module ------------------------------------------------------ */ | 437 | /* -- jit.opt module ------------------------------------------------------ */ |
420 | 438 | ||
421 | #if LJ_HASJIT | 439 | #if LJ_HASJIT |
@@ -513,6 +531,104 @@ LJLIB_CF(jit_opt_start) | |||
513 | 531 | ||
514 | #endif | 532 | #endif |
515 | 533 | ||
534 | /* -- jit.profile module -------------------------------------------------- */ | ||
535 | |||
536 | #if LJ_HASPROFILE | ||
537 | |||
538 | #define LJLIB_MODULE_jit_profile | ||
539 | |||
540 | /* Not loaded by default, use: local profile = require("jit.profile") */ | ||
541 | |||
542 | static const char KEY_PROFILE_THREAD = 't'; | ||
543 | static const char KEY_PROFILE_FUNC = 'f'; | ||
544 | |||
545 | static void jit_profile_callback(lua_State *L2, lua_State *L, int samples, | ||
546 | int vmstate) | ||
547 | { | ||
548 | TValue key; | ||
549 | cTValue *tv; | ||
550 | setlightudV(&key, (void *)&KEY_PROFILE_FUNC); | ||
551 | tv = lj_tab_get(L, tabV(registry(L)), &key); | ||
552 | if (tvisfunc(tv)) { | ||
553 | char vmst = (char)vmstate; | ||
554 | int status; | ||
555 | setfuncV(L2, L2->top++, funcV(tv)); | ||
556 | setthreadV(L2, L2->top++, L); | ||
557 | setintV(L2->top++, samples); | ||
558 | setstrV(L2, L2->top++, lj_str_new(L2, &vmst, 1)); | ||
559 | status = lua_pcall(L2, 3, 0, 0); /* callback(thread, samples, vmstate) */ | ||
560 | if (status) { | ||
561 | if (G(L2)->panic) G(L2)->panic(L2); | ||
562 | exit(EXIT_FAILURE); | ||
563 | } | ||
564 | lj_trace_abort(G(L2)); | ||
565 | } | ||
566 | } | ||
567 | |||
568 | /* profile.start(mode, cb) */ | ||
569 | LJLIB_CF(jit_profile_start) | ||
570 | { | ||
571 | GCtab *registry = tabV(registry(L)); | ||
572 | GCstr *mode = lj_lib_optstr(L, 1); | ||
573 | GCfunc *func = lj_lib_checkfunc(L, 2); | ||
574 | lua_State *L2 = lua_newthread(L); /* Thread that runs profiler callback. */ | ||
575 | TValue key; | ||
576 | /* Anchor thread and function in registry. */ | ||
577 | setlightudV(&key, (void *)&KEY_PROFILE_THREAD); | ||
578 | setthreadV(L, lj_tab_set(L, registry, &key), L2); | ||
579 | setlightudV(&key, (void *)&KEY_PROFILE_FUNC); | ||
580 | setfuncV(L, lj_tab_set(L, registry, &key), func); | ||
581 | lj_gc_anybarriert(L, registry); | ||
582 | luaJIT_profile_start(L, mode ? strdata(mode) : "", | ||
583 | (luaJIT_profile_callback)jit_profile_callback, L2); | ||
584 | return 0; | ||
585 | } | ||
586 | |||
587 | /* profile.stop() */ | ||
588 | LJLIB_CF(jit_profile_stop) | ||
589 | { | ||
590 | GCtab *registry; | ||
591 | TValue key; | ||
592 | luaJIT_profile_stop(L); | ||
593 | registry = tabV(registry(L)); | ||
594 | setlightudV(&key, (void *)&KEY_PROFILE_THREAD); | ||
595 | setnilV(lj_tab_set(L, registry, &key)); | ||
596 | setlightudV(&key, (void *)&KEY_PROFILE_FUNC); | ||
597 | setnilV(lj_tab_set(L, registry, &key)); | ||
598 | lj_gc_anybarriert(L, registry); | ||
599 | return 0; | ||
600 | } | ||
601 | |||
602 | /* dump = profile.dumpstack([thread,] fmt, depth) */ | ||
603 | LJLIB_CF(jit_profile_dumpstack) | ||
604 | { | ||
605 | lua_State *L2 = L; | ||
606 | int arg = 0; | ||
607 | size_t len; | ||
608 | int depth; | ||
609 | GCstr *fmt; | ||
610 | const char *p; | ||
611 | if (L->top > L->base && tvisthread(L->base)) { | ||
612 | L2 = threadV(L->base); | ||
613 | arg = 1; | ||
614 | } | ||
615 | fmt = lj_lib_checkstr(L, arg+1); | ||
616 | depth = lj_lib_checkint(L, arg+2); | ||
617 | p = luaJIT_profile_dumpstack(L2, strdata(fmt), depth, &len); | ||
618 | lua_pushlstring(L, p, len); | ||
619 | return 1; | ||
620 | } | ||
621 | |||
622 | #include "lj_libdef.h" | ||
623 | |||
624 | static int luaopen_jit_profile(lua_State *L) | ||
625 | { | ||
626 | LJ_LIB_REG(L, NULL, jit_profile); | ||
627 | return 1; | ||
628 | } | ||
629 | |||
630 | #endif | ||
631 | |||
516 | /* -- JIT compiler initialization ----------------------------------------- */ | 632 | /* -- JIT compiler initialization ----------------------------------------- */ |
517 | 633 | ||
518 | #if LJ_HASJIT | 634 | #if LJ_HASJIT |
@@ -538,38 +654,31 @@ static uint32_t jit_cpudetect(lua_State *L) | |||
538 | uint32_t features[4]; | 654 | uint32_t features[4]; |
539 | if (lj_vm_cpuid(0, vendor) && lj_vm_cpuid(1, features)) { | 655 | if (lj_vm_cpuid(0, vendor) && lj_vm_cpuid(1, features)) { |
540 | #if !LJ_HASJIT | 656 | #if !LJ_HASJIT |
541 | #define JIT_F_CMOV 1 | ||
542 | #define JIT_F_SSE2 2 | 657 | #define JIT_F_SSE2 2 |
543 | #endif | 658 | #endif |
544 | flags |= ((features[3] >> 15)&1) * JIT_F_CMOV; | ||
545 | flags |= ((features[3] >> 26)&1) * JIT_F_SSE2; | 659 | flags |= ((features[3] >> 26)&1) * JIT_F_SSE2; |
546 | #if LJ_HASJIT | 660 | #if LJ_HASJIT |
547 | flags |= ((features[2] >> 0)&1) * JIT_F_SSE3; | 661 | flags |= ((features[2] >> 0)&1) * JIT_F_SSE3; |
548 | flags |= ((features[2] >> 19)&1) * JIT_F_SSE4_1; | 662 | flags |= ((features[2] >> 19)&1) * JIT_F_SSE4_1; |
549 | if (vendor[2] == 0x6c65746e) { /* Intel. */ | 663 | if (vendor[2] == 0x6c65746e) { /* Intel. */ |
550 | if ((features[0] & 0x0ff00f00) == 0x00000f00) /* P4. */ | 664 | if ((features[0] & 0x0fff0ff0) == 0x000106c0) /* Atom. */ |
551 | flags |= JIT_F_P4; /* Currently unused. */ | ||
552 | else if ((features[0] & 0x0fff0ff0) == 0x000106c0) /* Atom. */ | ||
553 | flags |= JIT_F_LEA_AGU; | 665 | flags |= JIT_F_LEA_AGU; |
554 | } else if (vendor[2] == 0x444d4163) { /* AMD. */ | 666 | } else if (vendor[2] == 0x444d4163) { /* AMD. */ |
555 | uint32_t fam = (features[0] & 0x0ff00f00); | 667 | uint32_t fam = (features[0] & 0x0ff00f00); |
556 | if (fam == 0x00000f00) /* K8. */ | ||
557 | flags |= JIT_F_SPLIT_XMM; | ||
558 | if (fam >= 0x00000f00) /* K8, K10. */ | 668 | if (fam >= 0x00000f00) /* K8, K10. */ |
559 | flags |= JIT_F_PREFER_IMUL; | 669 | flags |= JIT_F_PREFER_IMUL; |
560 | } | 670 | } |
671 | if (vendor[0] >= 7) { | ||
672 | uint32_t xfeatures[4]; | ||
673 | lj_vm_cpuid(7, xfeatures); | ||
674 | flags |= ((xfeatures[1] >> 8)&1) * JIT_F_BMI2; | ||
675 | } | ||
561 | #endif | 676 | #endif |
562 | } | 677 | } |
563 | /* Check for required instruction set support on x86 (unnecessary on x64). */ | 678 | /* Check for required instruction set support on x86 (unnecessary on x64). */ |
564 | #if LJ_TARGET_X86 | 679 | #if LJ_TARGET_X86 |
565 | #if !defined(LUAJIT_CPU_NOCMOV) | ||
566 | if (!(flags & JIT_F_CMOV)) | ||
567 | luaL_error(L, "CPU not supported"); | ||
568 | #endif | ||
569 | #if defined(LUAJIT_CPU_SSE2) | ||
570 | if (!(flags & JIT_F_SSE2)) | 680 | if (!(flags & JIT_F_SSE2)) |
571 | luaL_error(L, "CPU does not support SSE2 (recompile without -DLUAJIT_CPU_SSE2)"); | 681 | luaL_error(L, "CPU with SSE2 required"); |
572 | #endif | ||
573 | #endif | 682 | #endif |
574 | #elif LJ_TARGET_ARM | 683 | #elif LJ_TARGET_ARM |
575 | #if LJ_HASJIT | 684 | #if LJ_HASJIT |
@@ -591,6 +700,8 @@ static uint32_t jit_cpudetect(lua_State *L) | |||
591 | ver >= 60 ? JIT_F_ARMV6_ : 0; | 700 | ver >= 60 ? JIT_F_ARMV6_ : 0; |
592 | flags |= LJ_ARCH_HASFPU == 0 ? 0 : ver >= 70 ? JIT_F_VFPV3 : JIT_F_VFPV2; | 701 | flags |= LJ_ARCH_HASFPU == 0 ? 0 : ver >= 70 ? JIT_F_VFPV3 : JIT_F_VFPV2; |
593 | #endif | 702 | #endif |
703 | #elif LJ_TARGET_ARM64 | ||
704 | /* No optional CPU features to detect (for now). */ | ||
594 | #elif LJ_TARGET_PPC | 705 | #elif LJ_TARGET_PPC |
595 | #if LJ_HASJIT | 706 | #if LJ_HASJIT |
596 | #if LJ_ARCH_SQRT | 707 | #if LJ_ARCH_SQRT |
@@ -600,8 +711,6 @@ static uint32_t jit_cpudetect(lua_State *L) | |||
600 | flags |= JIT_F_ROUND; | 711 | flags |= JIT_F_ROUND; |
601 | #endif | 712 | #endif |
602 | #endif | 713 | #endif |
603 | #elif LJ_TARGET_PPCSPE | ||
604 | /* Nothing to do. */ | ||
605 | #elif LJ_TARGET_MIPS | 714 | #elif LJ_TARGET_MIPS |
606 | #if LJ_HASJIT | 715 | #if LJ_HASJIT |
607 | /* Compile-time MIPS CPU detection. */ | 716 | /* Compile-time MIPS CPU detection. */ |
@@ -631,11 +740,7 @@ static void jit_init(lua_State *L) | |||
631 | uint32_t flags = jit_cpudetect(L); | 740 | uint32_t flags = jit_cpudetect(L); |
632 | #if LJ_HASJIT | 741 | #if LJ_HASJIT |
633 | jit_State *J = L2J(L); | 742 | jit_State *J = L2J(L); |
634 | #if LJ_TARGET_X86 | 743 | J->flags = flags | JIT_F_ON | JIT_F_OPT_DEFAULT; |
635 | /* Silently turn off the JIT compiler on CPUs without SSE2. */ | ||
636 | if ((flags & JIT_F_SSE2)) | ||
637 | #endif | ||
638 | J->flags = flags | JIT_F_ON | JIT_F_OPT_DEFAULT; | ||
639 | memcpy(J->param, jit_param_default, sizeof(J->param)); | 744 | memcpy(J->param, jit_param_default, sizeof(J->param)); |
640 | lj_dispatch_update(G(L)); | 745 | lj_dispatch_update(G(L)); |
641 | #else | 746 | #else |
@@ -645,19 +750,23 @@ static void jit_init(lua_State *L) | |||
645 | 750 | ||
646 | LUALIB_API int luaopen_jit(lua_State *L) | 751 | LUALIB_API int luaopen_jit(lua_State *L) |
647 | { | 752 | { |
753 | jit_init(L); | ||
648 | lua_pushliteral(L, LJ_OS_NAME); | 754 | lua_pushliteral(L, LJ_OS_NAME); |
649 | lua_pushliteral(L, LJ_ARCH_NAME); | 755 | lua_pushliteral(L, LJ_ARCH_NAME); |
650 | lua_pushinteger(L, LUAJIT_VERSION_NUM); | 756 | lua_pushinteger(L, LUAJIT_VERSION_NUM); |
651 | lua_pushliteral(L, LUAJIT_VERSION); | 757 | lua_pushliteral(L, LUAJIT_VERSION); |
652 | LJ_LIB_REG(L, LUA_JITLIBNAME, jit); | 758 | LJ_LIB_REG(L, LUA_JITLIBNAME, jit); |
759 | #if LJ_HASPROFILE | ||
760 | lj_lib_prereg(L, LUA_JITLIBNAME ".profile", luaopen_jit_profile, | ||
761 | tabref(L->env)); | ||
762 | #endif | ||
653 | #ifndef LUAJIT_DISABLE_JITUTIL | 763 | #ifndef LUAJIT_DISABLE_JITUTIL |
654 | LJ_LIB_REG(L, "jit.util", jit_util); | 764 | lj_lib_prereg(L, LUA_JITLIBNAME ".util", luaopen_jit_util, tabref(L->env)); |
655 | #endif | 765 | #endif |
656 | #if LJ_HASJIT | 766 | #if LJ_HASJIT |
657 | LJ_LIB_REG(L, "jit.opt", jit_opt); | 767 | LJ_LIB_REG(L, "jit.opt", jit_opt); |
658 | #endif | 768 | #endif |
659 | L->top -= 2; | 769 | L->top -= 2; |
660 | jit_init(L); | ||
661 | return 1; | 770 | return 1; |
662 | } | 771 | } |
663 | 772 | ||