diff options
Diffstat (limited to 'src/lj_trace.c')
-rw-r--r-- | src/lj_trace.c | 55 |
1 files changed, 52 insertions, 3 deletions
diff --git a/src/lj_trace.c b/src/lj_trace.c index 4608f81f..a0ff8864 100644 --- a/src/lj_trace.c +++ b/src/lj_trace.c | |||
@@ -821,7 +821,7 @@ static void trace_exit_regs(lua_State *L, ExitState *ex) | |||
821 | } | 821 | } |
822 | #endif | 822 | #endif |
823 | 823 | ||
824 | #ifdef EXITSTATE_PCREG | 824 | #if defined(EXITSTATE_PCREG) || (LJ_UNWIND_JIT && !EXITTRACE_VMSTATE) |
825 | /* Determine trace number from pc of exit instruction. */ | 825 | /* Determine trace number from pc of exit instruction. */ |
826 | static TraceNo trace_exit_find(jit_State *J, MCode *pc) | 826 | static TraceNo trace_exit_find(jit_State *J, MCode *pc) |
827 | { | 827 | { |
@@ -843,10 +843,18 @@ int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr) | |||
843 | lua_State *L = J->L; | 843 | lua_State *L = J->L; |
844 | ExitState *ex = (ExitState *)exptr; | 844 | ExitState *ex = (ExitState *)exptr; |
845 | ExitDataCP exd; | 845 | ExitDataCP exd; |
846 | int errcode; | 846 | int errcode, exitcode = J->exitcode; |
847 | TValue exiterr; | ||
847 | const BCIns *pc; | 848 | const BCIns *pc; |
848 | void *cf; | 849 | void *cf; |
849 | GCtrace *T; | 850 | GCtrace *T; |
851 | |||
852 | setnilV(&exiterr); | ||
853 | if (exitcode) { /* Trace unwound with error code. */ | ||
854 | J->exitcode = 0; | ||
855 | copyTV(L, &exiterr, L->top-1); | ||
856 | } | ||
857 | |||
850 | #ifdef EXITSTATE_PCREG | 858 | #ifdef EXITSTATE_PCREG |
851 | J->parent = trace_exit_find(J, (MCode *)(intptr_t)ex->gpr[EXITSTATE_PCREG]); | 859 | J->parent = trace_exit_find(J, (MCode *)(intptr_t)ex->gpr[EXITSTATE_PCREG]); |
852 | #endif | 860 | #endif |
@@ -866,6 +874,8 @@ int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr) | |||
866 | if (errcode) | 874 | if (errcode) |
867 | return -errcode; /* Return negated error code. */ | 875 | return -errcode; /* Return negated error code. */ |
868 | 876 | ||
877 | if (exitcode) copyTV(L, L->top++, &exiterr); /* Anchor the error object. */ | ||
878 | |||
869 | if (!(LJ_HASPROFILE && (G(L)->hookmask & HOOK_PROFILE))) | 879 | if (!(LJ_HASPROFILE && (G(L)->hookmask & HOOK_PROFILE))) |
870 | lj_vmevent_send(L, TEXIT, | 880 | lj_vmevent_send(L, TEXIT, |
871 | lj_state_checkstack(L, 4+RID_NUM_GPR+RID_NUM_FPR+LUA_MINSTACK); | 881 | lj_state_checkstack(L, 4+RID_NUM_GPR+RID_NUM_FPR+LUA_MINSTACK); |
@@ -877,7 +887,9 @@ int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr) | |||
877 | pc = exd.pc; | 887 | pc = exd.pc; |
878 | cf = cframe_raw(L->cframe); | 888 | cf = cframe_raw(L->cframe); |
879 | setcframe_pc(cf, pc); | 889 | setcframe_pc(cf, pc); |
880 | if (LJ_HASPROFILE && (G(L)->hookmask & HOOK_PROFILE)) { | 890 | if (exitcode) { |
891 | return -exitcode; | ||
892 | } else if (LJ_HASPROFILE && (G(L)->hookmask & HOOK_PROFILE)) { | ||
881 | /* Just exit to interpreter. */ | 893 | /* Just exit to interpreter. */ |
882 | } else if (G(L)->gc.state == GCSatomic || G(L)->gc.state == GCSfinalize) { | 894 | } else if (G(L)->gc.state == GCSatomic || G(L)->gc.state == GCSfinalize) { |
883 | if (!(G(L)->hookmask & HOOK_GC)) | 895 | if (!(G(L)->hookmask & HOOK_GC)) |
@@ -915,4 +927,41 @@ int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr) | |||
915 | } | 927 | } |
916 | } | 928 | } |
917 | 929 | ||
930 | #if LJ_UNWIND_JIT | ||
931 | /* Given an mcode address determine trace exit address for unwinding. */ | ||
932 | uintptr_t LJ_FASTCALL lj_trace_unwind(jit_State *J, uintptr_t addr, ExitNo *ep) | ||
933 | { | ||
934 | #if EXITTRACE_VMSTATE | ||
935 | TraceNo traceno = J2G(J)->vmstate; | ||
936 | #else | ||
937 | TraceNo traceno = trace_exit_find(J, (MCode *)addr); | ||
938 | #endif | ||
939 | GCtrace *T = traceref(J, traceno); | ||
940 | if (T | ||
941 | #if EXITTRACE_VMSTATE | ||
942 | && addr >= (uintptr_t)T->mcode && addr < (uintptr_t)T->mcode + T->szmcode | ||
943 | #endif | ||
944 | ) { | ||
945 | SnapShot *snap = T->snap; | ||
946 | SnapNo lo = 0, exitno = T->nsnap; | ||
947 | uintptr_t ofs = (uintptr_t)((MCode *)addr - T->mcode); /* MCode units! */ | ||
948 | /* Rightmost binary search for mcode offset to determine exit number. */ | ||
949 | do { | ||
950 | SnapNo mid = (lo+exitno) >> 1; | ||
951 | if (ofs < snap[mid].mcofs) exitno = mid; else lo = mid + 1; | ||
952 | } while (lo < exitno); | ||
953 | exitno--; | ||
954 | *ep = exitno; | ||
955 | #ifdef EXITSTUBS_PER_GROUP | ||
956 | return (uintptr_t)exitstub_addr(J, exitno); | ||
957 | #else | ||
958 | return (uintptr_t)exitstub_trace_addr(T, exitno); | ||
959 | #endif | ||
960 | } | ||
961 | /* Cannot correlate addr with trace/exit. This will be fatal. */ | ||
962 | lj_assertJ(0, "bad exit pc"); | ||
963 | return 0; | ||
964 | } | ||
965 | #endif | ||
966 | |||
918 | #endif | 967 | #endif |