diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/lj_arch.h | 12 | ||||
| -rw-r--r-- | src/lj_asm.c | 71 | ||||
| -rw-r--r-- | src/lj_dispatch.h | 4 | ||||
| -rw-r--r-- | src/lj_err.c | 247 | ||||
| -rw-r--r-- | src/lj_err.h | 19 | ||||
| -rw-r--r-- | src/lj_ffrecord.c | 2 | ||||
| -rw-r--r-- | src/lj_jit.h | 2 | ||||
| -rw-r--r-- | src/lj_mcode.c | 5 | ||||
| -rw-r--r-- | src/lj_opt_loop.c | 1 | ||||
| -rw-r--r-- | src/lj_record.c | 3 | ||||
| -rw-r--r-- | src/lj_snap.c | 1 | ||||
| -rw-r--r-- | src/lj_state.c | 1 | ||||
| -rw-r--r-- | src/lj_target_x86.h | 2 | ||||
| -rw-r--r-- | src/lj_trace.c | 55 | ||||
| -rw-r--r-- | src/lj_trace.h | 3 | ||||
| -rw-r--r-- | src/lj_vm.h | 3 | ||||
| -rw-r--r-- | src/vm_arm.dasc | 3 | ||||
| -rw-r--r-- | src/vm_arm64.dasc | 3 | ||||
| -rw-r--r-- | src/vm_mips.dasc | 9 | ||||
| -rw-r--r-- | src/vm_mips64.dasc | 9 | ||||
| -rw-r--r-- | src/vm_ppc.dasc | 3 | ||||
| -rw-r--r-- | src/vm_x64.dasc | 4 | ||||
| -rw-r--r-- | src/vm_x86.dasc | 4 |
23 files changed, 421 insertions, 45 deletions
diff --git a/src/lj_arch.h b/src/lj_arch.h index ac3e3753..0a6e1b9f 100644 --- a/src/lj_arch.h +++ b/src/lj_arch.h | |||
| @@ -173,6 +173,7 @@ | |||
| 173 | #define LJ_TARGET_X86 1 | 173 | #define LJ_TARGET_X86 1 |
| 174 | #define LJ_TARGET_X86ORX64 1 | 174 | #define LJ_TARGET_X86ORX64 1 |
| 175 | #define LJ_TARGET_EHRETREG 0 | 175 | #define LJ_TARGET_EHRETREG 0 |
| 176 | #define LJ_TARGET_EHRAREG 8 | ||
| 176 | #define LJ_TARGET_MASKSHIFT 1 | 177 | #define LJ_TARGET_MASKSHIFT 1 |
| 177 | #define LJ_TARGET_MASKROT 1 | 178 | #define LJ_TARGET_MASKROT 1 |
| 178 | #define LJ_TARGET_UNALIGNED 1 | 179 | #define LJ_TARGET_UNALIGNED 1 |
| @@ -186,6 +187,7 @@ | |||
| 186 | #define LJ_TARGET_X64 1 | 187 | #define LJ_TARGET_X64 1 |
| 187 | #define LJ_TARGET_X86ORX64 1 | 188 | #define LJ_TARGET_X86ORX64 1 |
| 188 | #define LJ_TARGET_EHRETREG 0 | 189 | #define LJ_TARGET_EHRETREG 0 |
| 190 | #define LJ_TARGET_EHRAREG 16 | ||
| 189 | #define LJ_TARGET_JUMPRANGE 31 /* +-2^31 = +-2GB */ | 191 | #define LJ_TARGET_JUMPRANGE 31 /* +-2^31 = +-2GB */ |
| 190 | #define LJ_TARGET_MASKSHIFT 1 | 192 | #define LJ_TARGET_MASKSHIFT 1 |
| 191 | #define LJ_TARGET_MASKROT 1 | 193 | #define LJ_TARGET_MASKROT 1 |
| @@ -211,6 +213,7 @@ | |||
| 211 | #define LJ_ABI_EABI 1 | 213 | #define LJ_ABI_EABI 1 |
| 212 | #define LJ_TARGET_ARM 1 | 214 | #define LJ_TARGET_ARM 1 |
| 213 | #define LJ_TARGET_EHRETREG 0 | 215 | #define LJ_TARGET_EHRETREG 0 |
| 216 | #define LJ_TARGET_EHRAREG 14 | ||
| 214 | #define LJ_TARGET_JUMPRANGE 25 /* +-2^25 = +-32MB */ | 217 | #define LJ_TARGET_JUMPRANGE 25 /* +-2^25 = +-32MB */ |
| 215 | #define LJ_TARGET_MASKSHIFT 0 | 218 | #define LJ_TARGET_MASKSHIFT 0 |
| 216 | #define LJ_TARGET_MASKROT 1 | 219 | #define LJ_TARGET_MASKROT 1 |
| @@ -241,6 +244,7 @@ | |||
| 241 | #endif | 244 | #endif |
| 242 | #define LJ_TARGET_ARM64 1 | 245 | #define LJ_TARGET_ARM64 1 |
| 243 | #define LJ_TARGET_EHRETREG 0 | 246 | #define LJ_TARGET_EHRETREG 0 |
| 247 | #define LJ_TARGET_EHRAREG 30 | ||
| 244 | #define LJ_TARGET_JUMPRANGE 27 /* +-2^27 = +-128MB */ | 248 | #define LJ_TARGET_JUMPRANGE 27 /* +-2^27 = +-128MB */ |
| 245 | #define LJ_TARGET_MASKSHIFT 1 | 249 | #define LJ_TARGET_MASKSHIFT 1 |
| 246 | #define LJ_TARGET_MASKROT 1 | 250 | #define LJ_TARGET_MASKROT 1 |
| @@ -296,6 +300,7 @@ | |||
| 296 | 300 | ||
| 297 | #define LJ_TARGET_PPC 1 | 301 | #define LJ_TARGET_PPC 1 |
| 298 | #define LJ_TARGET_EHRETREG 3 | 302 | #define LJ_TARGET_EHRETREG 3 |
| 303 | #define LJ_TARGET_EHRAREG 65 | ||
| 299 | #define LJ_TARGET_JUMPRANGE 25 /* +-2^25 = +-32MB */ | 304 | #define LJ_TARGET_JUMPRANGE 25 /* +-2^25 = +-32MB */ |
| 300 | #define LJ_TARGET_MASKSHIFT 0 | 305 | #define LJ_TARGET_MASKSHIFT 0 |
| 301 | #define LJ_TARGET_MASKROT 1 | 306 | #define LJ_TARGET_MASKROT 1 |
| @@ -398,6 +403,7 @@ | |||
| 398 | #endif | 403 | #endif |
| 399 | #define LJ_TARGET_MIPS 1 | 404 | #define LJ_TARGET_MIPS 1 |
| 400 | #define LJ_TARGET_EHRETREG 4 | 405 | #define LJ_TARGET_EHRETREG 4 |
| 406 | #define LJ_TARGET_EHRAREG 31 | ||
| 401 | #define LJ_TARGET_JUMPRANGE 27 /* 2*2^27 = 256MB-aligned region */ | 407 | #define LJ_TARGET_JUMPRANGE 27 /* 2*2^27 = 256MB-aligned region */ |
| 402 | #define LJ_TARGET_MASKSHIFT 1 | 408 | #define LJ_TARGET_MASKSHIFT 1 |
| 403 | #define LJ_TARGET_MASKROT 1 | 409 | #define LJ_TARGET_MASKROT 1 |
| @@ -631,6 +637,12 @@ extern void *LJ_WIN_LOADLIBA(const char *path); | |||
| 631 | #define LJ_UNWIND_EXT 0 | 637 | #define LJ_UNWIND_EXT 0 |
| 632 | #endif | 638 | #endif |
| 633 | 639 | ||
| 640 | #if LJ_UNWIND_EXT && LJ_HASJIT && !LJ_TARGET_ARM && !(LJ_ABI_WIN && LJ_TARGET_X86) | ||
| 641 | #define LJ_UNWIND_JIT 1 | ||
| 642 | #else | ||
| 643 | #define LJ_UNWIND_JIT 0 | ||
| 644 | #endif | ||
| 645 | |||
| 634 | /* Compatibility with Lua 5.1 vs. 5.2. */ | 646 | /* Compatibility with Lua 5.1 vs. 5.2. */ |
| 635 | #ifdef LUAJIT_ENABLE_LUA52COMPAT | 647 | #ifdef LUAJIT_ENABLE_LUA52COMPAT |
| 636 | #define LJ_52 1 | 648 | #define LJ_52 1 |
diff --git a/src/lj_asm.c b/src/lj_asm.c index 7c9a4237..8a516eba 100644 --- a/src/lj_asm.c +++ b/src/lj_asm.c | |||
| @@ -71,6 +71,7 @@ typedef struct ASMState { | |||
| 71 | IRRef snaprename; /* Rename highwater mark for snapshot check. */ | 71 | IRRef snaprename; /* Rename highwater mark for snapshot check. */ |
| 72 | SnapNo snapno; /* Current snapshot number. */ | 72 | SnapNo snapno; /* Current snapshot number. */ |
| 73 | SnapNo loopsnapno; /* Loop snapshot number. */ | 73 | SnapNo loopsnapno; /* Loop snapshot number. */ |
| 74 | int snapalloc; /* Current snapshot needs allocation. */ | ||
| 74 | 75 | ||
| 75 | IRRef fuseref; /* Fusion limit (loopref, 0 or FUSE_DISABLED). */ | 76 | IRRef fuseref; /* Fusion limit (loopref, 0 or FUSE_DISABLED). */ |
| 76 | IRRef sectref; /* Section base reference (loopref or 0). */ | 77 | IRRef sectref; /* Section base reference (loopref or 0). */ |
| @@ -84,6 +85,7 @@ typedef struct ASMState { | |||
| 84 | 85 | ||
| 85 | MCode *mcbot; /* Bottom of reserved MCode. */ | 86 | MCode *mcbot; /* Bottom of reserved MCode. */ |
| 86 | MCode *mctop; /* Top of generated MCode. */ | 87 | MCode *mctop; /* Top of generated MCode. */ |
| 88 | MCode *mctoporig; /* Original top of generated MCode. */ | ||
| 87 | MCode *mcloop; /* Pointer to loop MCode (or NULL). */ | 89 | MCode *mcloop; /* Pointer to loop MCode (or NULL). */ |
| 88 | MCode *invmcp; /* Points to invertible loop branch (or NULL). */ | 90 | MCode *invmcp; /* Points to invertible loop branch (or NULL). */ |
| 89 | MCode *flagmcp; /* Pending opportunity to merge flag setting ins. */ | 91 | MCode *flagmcp; /* Pending opportunity to merge flag setting ins. */ |
| @@ -947,9 +949,9 @@ static void asm_snap_alloc1(ASMState *as, IRRef ref) | |||
| 947 | } | 949 | } |
| 948 | 950 | ||
| 949 | /* Allocate refs escaping to a snapshot. */ | 951 | /* Allocate refs escaping to a snapshot. */ |
| 950 | static void asm_snap_alloc(ASMState *as) | 952 | static void asm_snap_alloc(ASMState *as, int snapno) |
| 951 | { | 953 | { |
| 952 | SnapShot *snap = &as->T->snap[as->snapno]; | 954 | SnapShot *snap = &as->T->snap[snapno]; |
| 953 | SnapEntry *map = &as->T->snapmap[snap->mapofs]; | 955 | SnapEntry *map = &as->T->snapmap[snap->mapofs]; |
| 954 | MSize n, nent = snap->nent; | 956 | MSize n, nent = snap->nent; |
| 955 | for (n = 0; n < nent; n++) { | 957 | for (n = 0; n < nent; n++) { |
| @@ -960,7 +962,7 @@ static void asm_snap_alloc(ASMState *as) | |||
| 960 | if (LJ_SOFTFP && (sn & SNAP_SOFTFPNUM)) { | 962 | if (LJ_SOFTFP && (sn & SNAP_SOFTFPNUM)) { |
| 961 | lj_assertA(irt_type(IR(ref+1)->t) == IRT_SOFTFP, | 963 | lj_assertA(irt_type(IR(ref+1)->t) == IRT_SOFTFP, |
| 962 | "snap %d[%d] points to bad SOFTFP IR %04d", | 964 | "snap %d[%d] points to bad SOFTFP IR %04d", |
| 963 | as->snapno, n, ref - REF_BIAS); | 965 | snapno, n, ref - REF_BIAS); |
| 964 | asm_snap_alloc1(as, ref+1); | 966 | asm_snap_alloc1(as, ref+1); |
| 965 | } | 967 | } |
| 966 | } | 968 | } |
| @@ -992,19 +994,16 @@ static int asm_snap_checkrename(ASMState *as, IRRef ren) | |||
| 992 | return 0; /* Not found. */ | 994 | return 0; /* Not found. */ |
| 993 | } | 995 | } |
| 994 | 996 | ||
| 995 | /* Prepare snapshot for next guard instruction. */ | 997 | /* Prepare snapshot for next guard or throwing instruction. */ |
| 996 | static void asm_snap_prep(ASMState *as) | 998 | static void asm_snap_prep(ASMState *as) |
| 997 | { | 999 | { |
| 998 | if (as->curins < as->snapref) { | 1000 | if (as->snapalloc) { |
| 999 | do { | 1001 | /* Alloc on first invocation for each snapshot. */ |
| 1000 | if (as->snapno == 0) return; /* Called by sunk stores before snap #0. */ | 1002 | as->snapalloc = 0; |
| 1001 | as->snapno--; | 1003 | asm_snap_alloc(as, as->snapno); |
| 1002 | as->snapref = as->T->snap[as->snapno].ref; | ||
| 1003 | } while (as->curins < as->snapref); | ||
| 1004 | asm_snap_alloc(as); | ||
| 1005 | as->snaprename = as->T->nins; | 1004 | as->snaprename = as->T->nins; |
| 1006 | } else { | 1005 | } else { |
| 1007 | /* Process any renames above the highwater mark. */ | 1006 | /* Check any renames above the highwater mark. */ |
| 1008 | for (; as->snaprename < as->T->nins; as->snaprename++) { | 1007 | for (; as->snaprename < as->T->nins; as->snaprename++) { |
| 1009 | IRIns *ir = &as->T->ir[as->snaprename]; | 1008 | IRIns *ir = &as->T->ir[as->snaprename]; |
| 1010 | if (asm_snap_checkrename(as, ir->op1)) | 1009 | if (asm_snap_checkrename(as, ir->op1)) |
| @@ -1013,6 +1012,35 @@ static void asm_snap_prep(ASMState *as) | |||
| 1013 | } | 1012 | } |
| 1014 | } | 1013 | } |
| 1015 | 1014 | ||
| 1015 | /* Move to previous snapshot when we cross the current snapshot ref. */ | ||
| 1016 | static void asm_snap_prev(ASMState *as) | ||
| 1017 | { | ||
| 1018 | if (as->curins < as->snapref) { | ||
| 1019 | ptrdiff_t ofs = as->mctoporig - as->mcp; | ||
| 1020 | if (ofs >= 0x10000) lj_trace_err(as->J, LJ_TRERR_MCODEOV); | ||
| 1021 | do { | ||
| 1022 | if (as->snapno == 0) return; | ||
| 1023 | as->snapno--; | ||
| 1024 | as->snapref = as->T->snap[as->snapno].ref; | ||
| 1025 | as->T->snap[as->snapno].mcofs = ofs; /* Remember mcode offset. */ | ||
| 1026 | } while (as->curins < as->snapref); /* May have no ins inbetween. */ | ||
| 1027 | as->snapalloc = 1; | ||
| 1028 | } | ||
| 1029 | } | ||
| 1030 | |||
| 1031 | /* Fixup snapshot mcode offsetst. */ | ||
| 1032 | static void asm_snap_fixup_mcofs(ASMState *as) | ||
| 1033 | { | ||
| 1034 | uint32_t sz = (uint32_t)(as->mctoporig - as->mcp); | ||
| 1035 | SnapShot *snap = as->T->snap; | ||
| 1036 | SnapNo i; | ||
| 1037 | for (i = as->T->nsnap-1; i > 0; i--) { | ||
| 1038 | /* Compute offset from mcode start and store in correct snapshot. */ | ||
| 1039 | snap[i].mcofs = (uint16_t)(sz - snap[i-1].mcofs); | ||
| 1040 | } | ||
| 1041 | snap[0].mcofs = 0; | ||
| 1042 | } | ||
| 1043 | |||
| 1016 | /* -- Miscellaneous helpers ----------------------------------------------- */ | 1044 | /* -- Miscellaneous helpers ----------------------------------------------- */ |
| 1017 | 1045 | ||
| 1018 | /* Calculate stack adjustment. */ | 1046 | /* Calculate stack adjustment. */ |
| @@ -1057,6 +1085,7 @@ static void asm_snew(ASMState *as, IRIns *ir) | |||
| 1057 | { | 1085 | { |
| 1058 | const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_str_new]; | 1086 | const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_str_new]; |
| 1059 | IRRef args[3]; | 1087 | IRRef args[3]; |
| 1088 | asm_snap_prep(as); | ||
| 1060 | args[0] = ASMREF_L; /* lua_State *L */ | 1089 | args[0] = ASMREF_L; /* lua_State *L */ |
| 1061 | args[1] = ir->op1; /* const char *str */ | 1090 | args[1] = ir->op1; /* const char *str */ |
| 1062 | args[2] = ir->op2; /* size_t len */ | 1091 | args[2] = ir->op2; /* size_t len */ |
| @@ -1069,6 +1098,7 @@ static void asm_tnew(ASMState *as, IRIns *ir) | |||
| 1069 | { | 1098 | { |
| 1070 | const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_tab_new1]; | 1099 | const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_tab_new1]; |
| 1071 | IRRef args[2]; | 1100 | IRRef args[2]; |
| 1101 | asm_snap_prep(as); | ||
| 1072 | args[0] = ASMREF_L; /* lua_State *L */ | 1102 | args[0] = ASMREF_L; /* lua_State *L */ |
| 1073 | args[1] = ASMREF_TMP1; /* uint32_t ahsize */ | 1103 | args[1] = ASMREF_TMP1; /* uint32_t ahsize */ |
| 1074 | as->gcsteps++; | 1104 | as->gcsteps++; |
| @@ -1081,6 +1111,7 @@ static void asm_tdup(ASMState *as, IRIns *ir) | |||
| 1081 | { | 1111 | { |
| 1082 | const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_tab_dup]; | 1112 | const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_tab_dup]; |
| 1083 | IRRef args[2]; | 1113 | IRRef args[2]; |
| 1114 | asm_snap_prep(as); | ||
| 1084 | args[0] = ASMREF_L; /* lua_State *L */ | 1115 | args[0] = ASMREF_L; /* lua_State *L */ |
| 1085 | args[1] = ir->op1; /* const GCtab *kt */ | 1116 | args[1] = ir->op1; /* const GCtab *kt */ |
| 1086 | as->gcsteps++; | 1117 | as->gcsteps++; |
| @@ -1201,6 +1232,7 @@ static void asm_tostr(ASMState *as, IRIns *ir) | |||
| 1201 | { | 1232 | { |
| 1202 | const CCallInfo *ci; | 1233 | const CCallInfo *ci; |
| 1203 | IRRef args[2]; | 1234 | IRRef args[2]; |
| 1235 | asm_snap_prep(as); | ||
| 1204 | args[0] = ASMREF_L; | 1236 | args[0] = ASMREF_L; |
| 1205 | as->gcsteps++; | 1237 | as->gcsteps++; |
| 1206 | if (ir->op2 == IRTOSTR_NUM) { | 1238 | if (ir->op2 == IRTOSTR_NUM) { |
| @@ -1257,6 +1289,7 @@ static void asm_newref(ASMState *as, IRIns *ir) | |||
| 1257 | IRRef args[3]; | 1289 | IRRef args[3]; |
| 1258 | if (ir->r == RID_SINK) | 1290 | if (ir->r == RID_SINK) |
| 1259 | return; | 1291 | return; |
| 1292 | asm_snap_prep(as); | ||
| 1260 | args[0] = ASMREF_L; /* lua_State *L */ | 1293 | args[0] = ASMREF_L; /* lua_State *L */ |
| 1261 | args[1] = ir->op1; /* GCtab *t */ | 1294 | args[1] = ir->op1; /* GCtab *t */ |
| 1262 | args[2] = ASMREF_TMP1; /* cTValue *key */ | 1295 | args[2] = ASMREF_TMP1; /* cTValue *key */ |
| @@ -1838,8 +1871,7 @@ static void asm_head_side(ASMState *as) | |||
| 1838 | 1871 | ||
| 1839 | if (as->snapno && as->topslot > as->parent->topslot) { | 1872 | if (as->snapno && as->topslot > as->parent->topslot) { |
| 1840 | /* Force snap #0 alloc to prevent register overwrite in stack check. */ | 1873 | /* Force snap #0 alloc to prevent register overwrite in stack check. */ |
| 1841 | as->snapno = 0; | 1874 | asm_snap_alloc(as, 0); |
| 1842 | asm_snap_alloc(as); | ||
| 1843 | } | 1875 | } |
| 1844 | allow = asm_head_side_base(as, irp, allow); | 1876 | allow = asm_head_side_base(as, irp, allow); |
| 1845 | 1877 | ||
| @@ -2100,6 +2132,7 @@ static void asm_setup_regsp(ASMState *as) | |||
| 2100 | as->snaprename = nins; | 2132 | as->snaprename = nins; |
| 2101 | as->snapref = nins; | 2133 | as->snapref = nins; |
| 2102 | as->snapno = T->nsnap; | 2134 | as->snapno = T->nsnap; |
| 2135 | as->snapalloc = 0; | ||
| 2103 | 2136 | ||
| 2104 | as->stopins = REF_BASE; | 2137 | as->stopins = REF_BASE; |
| 2105 | as->orignins = nins; | 2138 | as->orignins = nins; |
| @@ -2327,7 +2360,6 @@ void lj_asm_trace(jit_State *J, GCtrace *T) | |||
| 2327 | { | 2360 | { |
| 2328 | ASMState as_; | 2361 | ASMState as_; |
| 2329 | ASMState *as = &as_; | 2362 | ASMState *as = &as_; |
| 2330 | MCode *origtop; | ||
| 2331 | 2363 | ||
| 2332 | /* Remove nops/renames left over from ASM restart due to LJ_TRERR_MCODELM. */ | 2364 | /* Remove nops/renames left over from ASM restart due to LJ_TRERR_MCODELM. */ |
| 2333 | { | 2365 | { |
| @@ -2355,7 +2387,7 @@ void lj_asm_trace(jit_State *J, GCtrace *T) | |||
| 2355 | as->parent = J->parent ? traceref(J, J->parent) : NULL; | 2387 | as->parent = J->parent ? traceref(J, J->parent) : NULL; |
| 2356 | 2388 | ||
| 2357 | /* Reserve MCode memory. */ | 2389 | /* Reserve MCode memory. */ |
| 2358 | as->mctop = origtop = lj_mcode_reserve(J, &as->mcbot); | 2390 | as->mctop = as->mctoporig = lj_mcode_reserve(J, &as->mcbot); |
| 2359 | as->mcp = as->mctop; | 2391 | as->mcp = as->mctop; |
| 2360 | as->mclim = as->mcbot + MCLIM_REDZONE; | 2392 | as->mclim = as->mcbot + MCLIM_REDZONE; |
| 2361 | asm_setup_target(as); | 2393 | asm_setup_target(as); |
| @@ -2417,6 +2449,7 @@ void lj_asm_trace(jit_State *J, GCtrace *T) | |||
| 2417 | lj_assertA(!(LJ_32 && irt_isint64(ir->t)), | 2449 | lj_assertA(!(LJ_32 && irt_isint64(ir->t)), |
| 2418 | "IR %04d has unsplit 64 bit type", | 2450 | "IR %04d has unsplit 64 bit type", |
| 2419 | (int)(ir - as->ir) - REF_BIAS); | 2451 | (int)(ir - as->ir) - REF_BIAS); |
| 2452 | asm_snap_prev(as); | ||
| 2420 | if (!ra_used(ir) && !ir_sideeff(ir) && (as->flags & JIT_F_OPT_DCE)) | 2453 | if (!ra_used(ir) && !ir_sideeff(ir) && (as->flags & JIT_F_OPT_DCE)) |
| 2421 | continue; /* Dead-code elimination can be soooo easy. */ | 2454 | continue; /* Dead-code elimination can be soooo easy. */ |
| 2422 | if (irt_isguard(ir->t)) | 2455 | if (irt_isguard(ir->t)) |
| @@ -2450,6 +2483,9 @@ void lj_asm_trace(jit_State *J, GCtrace *T) | |||
| 2450 | memcpy(J->curfinal->ir + as->orignins, T->ir + as->orignins, | 2483 | memcpy(J->curfinal->ir + as->orignins, T->ir + as->orignins, |
| 2451 | (T->nins - as->orignins) * sizeof(IRIns)); /* Copy RENAMEs. */ | 2484 | (T->nins - as->orignins) * sizeof(IRIns)); /* Copy RENAMEs. */ |
| 2452 | T->nins = J->curfinal->nins; | 2485 | T->nins = J->curfinal->nins; |
| 2486 | /* Fill mcofs of any unprocessed snapshots. */ | ||
| 2487 | as->curins = REF_FIRST; | ||
| 2488 | asm_snap_prev(as); | ||
| 2453 | break; /* Done. */ | 2489 | break; /* Done. */ |
| 2454 | } | 2490 | } |
| 2455 | 2491 | ||
| @@ -2471,10 +2507,11 @@ void lj_asm_trace(jit_State *J, GCtrace *T) | |||
| 2471 | if (!as->loopref) | 2507 | if (!as->loopref) |
| 2472 | asm_tail_fixup(as, T->link); /* Note: this may change as->mctop! */ | 2508 | asm_tail_fixup(as, T->link); /* Note: this may change as->mctop! */ |
| 2473 | T->szmcode = (MSize)((char *)as->mctop - (char *)as->mcp); | 2509 | T->szmcode = (MSize)((char *)as->mctop - (char *)as->mcp); |
| 2510 | asm_snap_fixup_mcofs(as); | ||
| 2474 | #if LJ_TARGET_MCODE_FIXUP | 2511 | #if LJ_TARGET_MCODE_FIXUP |
| 2475 | asm_mcode_fixup(T->mcode, T->szmcode); | 2512 | asm_mcode_fixup(T->mcode, T->szmcode); |
| 2476 | #endif | 2513 | #endif |
| 2477 | lj_mcode_sync(T->mcode, origtop); | 2514 | lj_mcode_sync(T->mcode, as->mctoporig); |
| 2478 | } | 2515 | } |
| 2479 | 2516 | ||
| 2480 | #undef IR | 2517 | #undef IR |
diff --git a/src/lj_dispatch.h b/src/lj_dispatch.h index be7c410a..2331bd42 100644 --- a/src/lj_dispatch.h +++ b/src/lj_dispatch.h | |||
| @@ -31,7 +31,7 @@ extern double __divdf3(double a, double b); | |||
| 31 | #define SFGOTDEF(_) | 31 | #define SFGOTDEF(_) |
| 32 | #endif | 32 | #endif |
| 33 | #if LJ_HASJIT | 33 | #if LJ_HASJIT |
| 34 | #define JITGOTDEF(_) _(lj_trace_exit) _(lj_trace_hot) | 34 | #define JITGOTDEF(_) _(lj_err_trace) _(lj_trace_exit) _(lj_trace_hot) |
| 35 | #else | 35 | #else |
| 36 | #define JITGOTDEF(_) | 36 | #define JITGOTDEF(_) |
| 37 | #endif | 37 | #endif |
| @@ -46,7 +46,7 @@ extern double __divdf3(double a, double b); | |||
| 46 | _(asin) _(acos) _(atan) _(sinh) _(cosh) _(tanh) _(frexp) _(modf) _(atan2) \ | 46 | _(asin) _(acos) _(atan) _(sinh) _(cosh) _(tanh) _(frexp) _(modf) _(atan2) \ |
| 47 | _(pow) _(fmod) _(ldexp) _(lj_vm_modi) \ | 47 | _(pow) _(fmod) _(ldexp) _(lj_vm_modi) \ |
| 48 | _(lj_dispatch_call) _(lj_dispatch_ins) _(lj_dispatch_stitch) \ | 48 | _(lj_dispatch_call) _(lj_dispatch_ins) _(lj_dispatch_stitch) \ |
| 49 | _(lj_dispatch_profile) _(lj_err_throw) _(lj_err_run) \ | 49 | _(lj_dispatch_profile) _(lj_err_throw) \ |
| 50 | _(lj_ffh_coroutine_wrap_err) _(lj_func_closeuv) _(lj_func_newL_gc) \ | 50 | _(lj_ffh_coroutine_wrap_err) _(lj_func_closeuv) _(lj_func_newL_gc) \ |
| 51 | _(lj_gc_barrieruv) _(lj_gc_step) _(lj_gc_step_fixtop) _(lj_meta_arith) \ | 51 | _(lj_gc_barrieruv) _(lj_gc_step) _(lj_gc_step_fixtop) _(lj_meta_arith) \ |
| 52 | _(lj_meta_call) _(lj_meta_cat) _(lj_meta_comp) _(lj_meta_equal) \ | 52 | _(lj_meta_call) _(lj_meta_cat) _(lj_meta_comp) _(lj_meta_equal) \ |
diff --git a/src/lj_err.c b/src/lj_err.c index ba0fac0a..9fc3adc7 100644 --- a/src/lj_err.c +++ b/src/lj_err.c | |||
| @@ -52,6 +52,11 @@ | |||
| 52 | ** the wrapper function feature. Lua errors thrown through C++ frames | 52 | ** the wrapper function feature. Lua errors thrown through C++ frames |
| 53 | ** cannot be caught by C++ code and C++ destructors are not run. | 53 | ** cannot be caught by C++ code and C++ destructors are not run. |
| 54 | ** | 54 | ** |
| 55 | ** - EXT can handle errors from internal helper functions that are called | ||
| 56 | ** from JIT-compiled code (except for Windows/x86 and 32 bit ARM). | ||
| 57 | ** INT has no choice but to call the panic handler, if this happens. | ||
| 58 | ** Note: this is mainly relevant for out-of-memory errors. | ||
| 59 | ** | ||
| 55 | ** EXT is the default on all systems where the toolchain produces unwind | 60 | ** EXT is the default on all systems where the toolchain produces unwind |
| 56 | ** tables by default (*). This is hard-coded and/or detected in src/Makefile. | 61 | ** tables by default (*). This is hard-coded and/or detected in src/Makefile. |
| 57 | ** You can thwart the detection with: TARGET_XCFLAGS=-DLUAJIT_UNWIND_INTERNAL | 62 | ** You can thwart the detection with: TARGET_XCFLAGS=-DLUAJIT_UNWIND_INTERNAL |
| @@ -305,12 +310,59 @@ LJ_FUNCA int lj_err_unwind_win(EXCEPTION_RECORD *rec, | |||
| 305 | return 1; /* ExceptionContinueSearch */ | 310 | return 1; /* ExceptionContinueSearch */ |
| 306 | } | 311 | } |
| 307 | 312 | ||
| 313 | #if LJ_UNWIND_JIT | ||
| 314 | |||
| 315 | #if LJ_TARGET_X64 | ||
| 316 | #define CONTEXT_REG_PC Rip | ||
| 317 | #elif LJ_TARGET_ARM64 | ||
| 318 | #define CONTEXT_REG_PC Pc | ||
| 319 | #else | ||
| 320 | #error "NYI: Windows arch-specific unwinder for JIT-compiled code" | ||
| 321 | #endif | ||
| 322 | |||
| 323 | /* Windows unwinder for JIT-compiled code. */ | ||
| 324 | static void err_unwind_win_jit(global_State *g, int errcode) | ||
| 325 | { | ||
| 326 | CONTEXT ctx; | ||
| 327 | UNWIND_HISTORY_TABLE hist; | ||
| 328 | |||
| 329 | memset(&hist, 0, sizeof(hist)); | ||
| 330 | RtlCaptureContext(&ctx); | ||
| 331 | while (1) { | ||
| 332 | uintptr_t frame, base, addr = ctx.CONTEXT_REG_PC; | ||
| 333 | void *hdata; | ||
| 334 | PRUNTIME_FUNCTION func = RtlLookupFunctionEntry(addr, &base, &hist); | ||
| 335 | if (!func) { /* Found frame without .pdata: must be JIT-compiled code. */ | ||
| 336 | ExitNo exitno; | ||
| 337 | uintptr_t stub = lj_trace_unwind(G2J(g), addr - sizeof(MCode), &exitno); | ||
| 338 | if (stub) { /* Jump to side exit to unwind the trace. */ | ||
| 339 | ctx.CONTEXT_REG_PC = stub; | ||
| 340 | G2J(g)->exitcode = errcode; | ||
| 341 | RtlRestoreContext(&ctx, NULL); /* Does not return. */ | ||
| 342 | } | ||
| 343 | break; | ||
| 344 | } | ||
| 345 | RtlVirtualUnwind(UNW_FLAG_NHANDLER, base, addr, func, | ||
| 346 | &ctx, &hdata, &frame, NULL); | ||
| 347 | if (!addr) break; | ||
| 348 | } | ||
| 349 | /* Unwinding failed, if we end up here. */ | ||
| 350 | } | ||
| 351 | #endif | ||
| 352 | |||
| 308 | /* Raise Windows exception. */ | 353 | /* Raise Windows exception. */ |
| 309 | static void err_raise_ext(global_State *g, int errcode) | 354 | static void err_raise_ext(global_State *g, int errcode) |
| 310 | { | 355 | { |
| 311 | #if LJ_HASJIT | 356 | #if LJ_UNWIND_JIT |
| 357 | if (tvref(g->jit_base)) { | ||
| 358 | err_unwind_win_jit(g, errcode); | ||
| 359 | return; /* Unwinding failed. */ | ||
| 360 | } | ||
| 361 | #elif LJ_HASJIT | ||
| 362 | /* Cannot catch on-trace errors for Windows/x86 SEH. Unwind to interpreter. */ | ||
| 312 | setmref(g->jit_base, NULL); | 363 | setmref(g->jit_base, NULL); |
| 313 | #endif | 364 | #endif |
| 365 | UNUSED(g); | ||
| 314 | RaiseException(LJ_EXCODE_MAKE(errcode), 1 /* EH_NONCONTINUABLE */, 0, NULL); | 366 | RaiseException(LJ_EXCODE_MAKE(errcode), 1 /* EH_NONCONTINUABLE */, 0, NULL); |
| 315 | } | 367 | } |
| 316 | 368 | ||
| @@ -324,6 +376,7 @@ static void err_raise_ext(global_State *g, int errcode) | |||
| 324 | typedef struct _Unwind_Context _Unwind_Context; | 376 | typedef struct _Unwind_Context _Unwind_Context; |
| 325 | 377 | ||
| 326 | #define _URC_OK 0 | 378 | #define _URC_OK 0 |
| 379 | #define _URC_FATAL_PHASE2_ERROR 2 | ||
| 327 | #define _URC_FATAL_PHASE1_ERROR 3 | 380 | #define _URC_FATAL_PHASE1_ERROR 3 |
| 328 | #define _URC_HANDLER_FOUND 6 | 381 | #define _URC_HANDLER_FOUND 6 |
| 329 | #define _URC_INSTALL_CONTEXT 7 | 382 | #define _URC_INSTALL_CONTEXT 7 |
| @@ -343,9 +396,11 @@ typedef struct _Unwind_Exception | |||
| 343 | void (*excleanup)(int, struct _Unwind_Exception *); | 396 | void (*excleanup)(int, struct _Unwind_Exception *); |
| 344 | uintptr_t p1, p2; | 397 | uintptr_t p1, p2; |
| 345 | } __attribute__((__aligned__)) _Unwind_Exception; | 398 | } __attribute__((__aligned__)) _Unwind_Exception; |
| 399 | #define UNWIND_EXCEPTION_TYPE _Unwind_Exception | ||
| 346 | 400 | ||
| 347 | extern uintptr_t _Unwind_GetCFA(_Unwind_Context *); | 401 | extern uintptr_t _Unwind_GetCFA(_Unwind_Context *); |
| 348 | extern void _Unwind_SetGR(_Unwind_Context *, int, uintptr_t); | 402 | extern void _Unwind_SetGR(_Unwind_Context *, int, uintptr_t); |
| 403 | extern uintptr_t _Unwind_GetIP(_Unwind_Context *); | ||
| 349 | extern void _Unwind_SetIP(_Unwind_Context *, uintptr_t); | 404 | extern void _Unwind_SetIP(_Unwind_Context *, uintptr_t); |
| 350 | extern void _Unwind_DeleteException(_Unwind_Exception *); | 405 | extern void _Unwind_DeleteException(_Unwind_Exception *); |
| 351 | extern int _Unwind_RaiseException(_Unwind_Exception *); | 406 | extern int _Unwind_RaiseException(_Unwind_Exception *); |
| @@ -418,8 +473,130 @@ LJ_FUNCA int lj_err_unwind_dwarf(int version, int actions, | |||
| 418 | return _URC_CONTINUE_UNWIND; | 473 | return _URC_CONTINUE_UNWIND; |
| 419 | } | 474 | } |
| 420 | 475 | ||
| 421 | #if LJ_UNWIND_EXT | 476 | #if LJ_UNWIND_EXT && defined(LUA_USE_ASSERT) |
| 422 | static __thread _Unwind_Exception static_uex; | 477 | struct dwarf_eh_bases { void *tbase, *dbase, *func; }; |
| 478 | extern const void *_Unwind_Find_FDE(void *pc, struct dwarf_eh_bases *bases); | ||
| 479 | |||
| 480 | /* Verify that external error handling actually has a chance to work. */ | ||
| 481 | void lj_err_verify(void) | ||
| 482 | { | ||
| 483 | struct dwarf_eh_bases ehb; | ||
| 484 | lj_assertX(_Unwind_Find_FDE((void *)lj_err_throw, &ehb), "broken build: external frame unwinding enabled, but missing -funwind-tables"); | ||
| 485 | lj_assertX(_Unwind_Find_FDE((void *)_Unwind_RaiseException, &ehb), "broken build: external frame unwinding enabled, but system libraries have no unwind tables"); | ||
| 486 | } | ||
| 487 | #endif | ||
| 488 | |||
| 489 | #if LJ_UNWIND_JIT | ||
| 490 | /* DWARF2 personality handler for JIT-compiled code. */ | ||
| 491 | static int err_unwind_jit(int version, int actions, | ||
| 492 | uint64_t uexclass, _Unwind_Exception *uex, _Unwind_Context *ctx) | ||
| 493 | { | ||
| 494 | /* NYI: FFI C++ exception interoperability. */ | ||
| 495 | if (version != 1 || !LJ_UEXCLASS_CHECK(uexclass)) | ||
| 496 | return _URC_FATAL_PHASE1_ERROR; | ||
| 497 | if ((actions & _UA_SEARCH_PHASE)) { | ||
| 498 | return _URC_HANDLER_FOUND; | ||
| 499 | } | ||
| 500 | if ((actions & _UA_CLEANUP_PHASE)) { | ||
| 501 | global_State *g = *(global_State **)(uex+1); | ||
| 502 | ExitNo exitno; | ||
| 503 | uintptr_t addr = _Unwind_GetIP(ctx); /* Return address _after_ call. */ | ||
| 504 | uintptr_t stub = lj_trace_unwind(G2J(g), addr - sizeof(MCode), &exitno); | ||
| 505 | lj_assertG(tvref(g->jit_base), "unexpected throw across mcode frame"); | ||
| 506 | if (stub) { /* Jump to side exit to unwind the trace. */ | ||
| 507 | G2J(g)->exitcode = LJ_UEXCLASS_ERRCODE(uexclass); | ||
| 508 | #ifdef LJ_TARGET_MIPS | ||
| 509 | _Unwind_SetGR(ctx, 4, stub); | ||
| 510 | _Unwind_SetGR(ctx, 5, exitno); | ||
| 511 | _Unwind_SetIP(ctx, (uintptr_t)(void *)lj_vm_unwind_stub); | ||
| 512 | #else | ||
| 513 | _Unwind_SetIP(ctx, stub); | ||
| 514 | #endif | ||
| 515 | return _URC_INSTALL_CONTEXT; | ||
| 516 | } | ||
| 517 | return _URC_FATAL_PHASE2_ERROR; | ||
| 518 | } | ||
| 519 | return _URC_FATAL_PHASE1_ERROR; | ||
| 520 | } | ||
| 521 | |||
| 522 | /* DWARF2 template frame info for JIT-compiled code. | ||
| 523 | ** | ||
| 524 | ** After copying the template to the start of the mcode segment, | ||
| 525 | ** the frame handler function and the code size is patched. | ||
| 526 | ** The frame handler always installs a new context to jump to the exit, | ||
| 527 | ** so don't bother to add any unwind opcodes. | ||
| 528 | */ | ||
| 529 | static const uint8_t err_frame_jit_template[] = { | ||
| 530 | #if LJ_BE | ||
| 531 | 0,0,0, | ||
| 532 | #endif | ||
| 533 | LJ_64 ? 0x1c : 0x14, /* CIE length. */ | ||
| 534 | #if LJ_LE | ||
| 535 | 0,0,0, | ||
| 536 | #endif | ||
| 537 | 0,0,0,0, 1, 'z','P','R',0, /* CIE mark, CIE version, augmentation. */ | ||
| 538 | 1, LJ_64 ? 0x78 : 0x7c, LJ_TARGET_EHRAREG, /* Code/data align, RA. */ | ||
| 539 | #if LJ_64 | ||
| 540 | 10, 0, 0,0,0,0,0,0,0,0, 0x1b, /* Aug. data ABS handler, PCREL|SDATA4 code. */ | ||
| 541 | 0,0,0,0,0, /* Alignment. */ | ||
| 542 | #else | ||
| 543 | 6, 0, 0,0,0,0, 0x1b, /* Aug. data ABS handler, PCREL|SDATA4 code. */ | ||
| 544 | 0, /* Alignment. */ | ||
| 545 | #endif | ||
| 546 | #if LJ_BE | ||
| 547 | 0,0,0, | ||
| 548 | #endif | ||
| 549 | LJ_64 ? 0x14 : 0x10, /* FDE length. */ | ||
| 550 | 0,0,0, | ||
| 551 | LJ_64 ? 0x24 : 0x1c, /* CIE offset. */ | ||
| 552 | 0,0,0, | ||
| 553 | LJ_64 ? 0x14 : 0x10, /* Code offset. After Final FDE. */ | ||
| 554 | #if LJ_LE | ||
| 555 | 0,0,0, | ||
| 556 | #endif | ||
| 557 | 0,0,0,0, 0, 0,0,0, /* Code size, augmentation length, alignment. */ | ||
| 558 | #if LJ_64 | ||
| 559 | 0,0,0,0, /* Alignment. */ | ||
| 560 | #endif | ||
| 561 | 0,0,0,0 /* Final FDE. */ | ||
| 562 | }; | ||
| 563 | |||
| 564 | #define ERR_FRAME_JIT_OFS_HANDLER 0x12 | ||
| 565 | #define ERR_FRAME_JIT_OFS_FDE (LJ_64 ? 0x20 : 0x18) | ||
| 566 | #define ERR_FRAME_JIT_OFS_CODE_SIZE (LJ_64 ? 0x2c : 0x24) | ||
| 567 | #if LJ_TARGET_OSX | ||
| 568 | #define ERR_FRAME_JIT_OFS_REGISTER ERR_FRAME_JIT_OFS_FDE | ||
| 569 | #else | ||
| 570 | #define ERR_FRAME_JIT_OFS_REGISTER 0 | ||
| 571 | #endif | ||
| 572 | |||
| 573 | extern void __register_frame(const void *); | ||
| 574 | extern void __deregister_frame(const void *); | ||
| 575 | |||
| 576 | uint8_t *lj_err_register_mcode(void *base, size_t sz, uint8_t *info) | ||
| 577 | { | ||
| 578 | void **handler; | ||
| 579 | memcpy(info, err_frame_jit_template, sizeof(err_frame_jit_template)); | ||
| 580 | handler = (void *)err_unwind_jit; | ||
| 581 | memcpy(info + ERR_FRAME_JIT_OFS_HANDLER, &handler, sizeof(handler)); | ||
| 582 | *(uint32_t *)(info + ERR_FRAME_JIT_OFS_CODE_SIZE) = | ||
| 583 | (uint32_t)(sz - sizeof(err_frame_jit_template) - (info - (uint8_t *)base)); | ||
| 584 | __register_frame(info + ERR_FRAME_JIT_OFS_REGISTER); | ||
| 585 | #ifdef LUA_USE_ASSERT | ||
| 586 | { | ||
| 587 | struct dwarf_eh_bases ehb; | ||
| 588 | lj_assertX(_Unwind_Find_FDE(info + sizeof(err_frame_jit_template)+1, &ehb), | ||
| 589 | "bad JIT unwind table registration"); | ||
| 590 | } | ||
| 591 | #endif | ||
| 592 | return info + sizeof(err_frame_jit_template); | ||
| 593 | } | ||
| 594 | |||
| 595 | void lj_err_deregister_mcode(void *base, size_t sz, uint8_t *info) | ||
| 596 | { | ||
| 597 | UNUSED(base); UNUSED(sz); | ||
| 598 | __deregister_frame(info + ERR_FRAME_JIT_OFS_REGISTER); | ||
| 599 | } | ||
| 423 | #endif | 600 | #endif |
| 424 | 601 | ||
| 425 | #else /* LJ_TARGET_ARM */ | 602 | #else /* LJ_TARGET_ARM */ |
| @@ -430,6 +607,7 @@ static __thread _Unwind_Exception static_uex; | |||
| 430 | #define _US_FORCE_UNWIND 8 | 607 | #define _US_FORCE_UNWIND 8 |
| 431 | 608 | ||
| 432 | typedef struct _Unwind_Control_Block _Unwind_Control_Block; | 609 | typedef struct _Unwind_Control_Block _Unwind_Control_Block; |
| 610 | #define UNWIND_EXCEPTION_TYPE _Unwind_Control_Block | ||
| 433 | 611 | ||
| 434 | struct _Unwind_Control_Block { | 612 | struct _Unwind_Control_Block { |
| 435 | uint64_t exclass; | 613 | uint64_t exclass; |
| @@ -488,25 +666,62 @@ LJ_FUNCA int lj_err_unwind_arm(int state, _Unwind_Control_Block *ucb, | |||
| 488 | } | 666 | } |
| 489 | if (__gnu_unwind_frame(ucb, ctx) != _URC_OK) | 667 | if (__gnu_unwind_frame(ucb, ctx) != _URC_OK) |
| 490 | return _URC_FAILURE; | 668 | return _URC_FAILURE; |
| 669 | #ifdef LUA_USE_ASSERT | ||
| 670 | /* We should never get here unless this is a forced unwind aka backtrace. */ | ||
| 671 | if (_Unwind_GetGR(ctx, 0) == 0xff33aa77) { | ||
| 672 | _Unwind_SetGR(ctx, 0, 0xff33aa88); | ||
| 673 | } | ||
| 674 | #endif | ||
| 491 | return _URC_CONTINUE_UNWIND; | 675 | return _URC_CONTINUE_UNWIND; |
| 492 | } | 676 | } |
| 493 | 677 | ||
| 494 | #if LJ_UNWIND_EXT | 678 | #if LJ_UNWIND_EXT && defined(LUA_USE_ASSERT) |
| 495 | static __thread _Unwind_Control_Block static_uex; | 679 | typedef int (*_Unwind_Trace_Fn)(_Unwind_Context *, void *); |
| 680 | extern int _Unwind_Backtrace(_Unwind_Trace_Fn, void *); | ||
| 681 | |||
| 682 | static int err_verify_bt(_Unwind_Context *ctx, int *got) | ||
| 683 | { | ||
| 684 | if (_Unwind_GetGR(ctx, 0) == 0xff33aa88) { *got = 2; } | ||
| 685 | else if (*got == 0) { *got = 1; _Unwind_SetGR(ctx, 0, 0xff33aa77); } | ||
| 686 | return _URC_OK; | ||
| 687 | } | ||
| 688 | |||
| 689 | /* Verify that external error handling actually has a chance to work. */ | ||
| 690 | void lj_err_verify(void) | ||
| 691 | { | ||
| 692 | int got = 0; | ||
| 693 | _Unwind_Backtrace((_Unwind_Trace_Fn)err_verify_bt, &got); | ||
| 694 | lj_assertX(got == 2, "broken build: external frame unwinding enabled, but missing -funwind-tables"); | ||
| 695 | } | ||
| 496 | #endif | 696 | #endif |
| 697 | |||
| 698 | /* | ||
| 699 | ** Note: LJ_UNWIND_JIT is not implemented for 32 bit ARM. | ||
| 700 | ** | ||
| 701 | ** The quirky ARM unwind API doesn't have __register_frame(). | ||
| 702 | ** A potential workaround might involve _Unwind_Backtrace. | ||
| 703 | ** But most 32 bit ARM targets don't qualify for LJ_UNWIND_EXT, anyway, | ||
| 704 | ** since they are built without unwind tables by default. | ||
| 705 | */ | ||
| 706 | |||
| 497 | #endif /* LJ_TARGET_ARM */ | 707 | #endif /* LJ_TARGET_ARM */ |
| 498 | 708 | ||
| 709 | |||
| 499 | #if LJ_UNWIND_EXT | 710 | #if LJ_UNWIND_EXT |
| 711 | static __thread struct { | ||
| 712 | UNWIND_EXCEPTION_TYPE ex; | ||
| 713 | global_State *g; | ||
| 714 | } static_uex; | ||
| 715 | |||
| 500 | /* Raise external exception. */ | 716 | /* Raise external exception. */ |
| 501 | static void err_raise_ext(global_State *g, int errcode) | 717 | static void err_raise_ext(global_State *g, int errcode) |
| 502 | { | 718 | { |
| 503 | #if LJ_HASJIT | ||
| 504 | setmref(g->jit_base, NULL); | ||
| 505 | #endif | ||
| 506 | memset(&static_uex, 0, sizeof(static_uex)); | 719 | memset(&static_uex, 0, sizeof(static_uex)); |
| 507 | static_uex.exclass = LJ_UEXCLASS_MAKE(errcode); | 720 | static_uex.ex.exclass = LJ_UEXCLASS_MAKE(errcode); |
| 508 | _Unwind_RaiseException(&static_uex); | 721 | static_uex.g = g; |
| 722 | _Unwind_RaiseException(&static_uex.ex); | ||
| 509 | } | 723 | } |
| 724 | |||
| 510 | #endif | 725 | #endif |
| 511 | 726 | ||
| 512 | #endif | 727 | #endif |
| @@ -615,7 +830,7 @@ static ptrdiff_t finderrfunc(lua_State *L) | |||
| 615 | /* Runtime error. */ | 830 | /* Runtime error. */ |
| 616 | LJ_NOINLINE void LJ_FASTCALL lj_err_run(lua_State *L) | 831 | LJ_NOINLINE void LJ_FASTCALL lj_err_run(lua_State *L) |
| 617 | { | 832 | { |
| 618 | ptrdiff_t ef = finderrfunc(L); | 833 | ptrdiff_t ef = (LJ_HASJIT && tvref(G(L)->jit_base)) ? 0 : finderrfunc(L); |
| 619 | if (ef) { | 834 | if (ef) { |
| 620 | TValue *errfunc = restorestack(L, ef); | 835 | TValue *errfunc = restorestack(L, ef); |
| 621 | TValue *top = L->top; | 836 | TValue *top = L->top; |
| @@ -634,6 +849,16 @@ LJ_NOINLINE void LJ_FASTCALL lj_err_run(lua_State *L) | |||
| 634 | lj_err_throw(L, LUA_ERRRUN); | 849 | lj_err_throw(L, LUA_ERRRUN); |
| 635 | } | 850 | } |
| 636 | 851 | ||
| 852 | #if LJ_HASJIT | ||
| 853 | LJ_NOINLINE void LJ_FASTCALL lj_err_trace(lua_State *L, int errcode) | ||
| 854 | { | ||
| 855 | if (errcode == LUA_ERRRUN) | ||
| 856 | lj_err_run(L); | ||
| 857 | else | ||
| 858 | lj_err_throw(L, errcode); | ||
| 859 | } | ||
| 860 | #endif | ||
| 861 | |||
| 637 | /* Formatted runtime error message. */ | 862 | /* Formatted runtime error message. */ |
| 638 | LJ_NORET LJ_NOINLINE static void err_msgv(lua_State *L, ErrMsg em, ...) | 863 | LJ_NORET LJ_NOINLINE static void err_msgv(lua_State *L, ErrMsg em, ...) |
| 639 | { | 864 | { |
diff --git a/src/lj_err.h b/src/lj_err.h index 770553fc..2e8a251f 100644 --- a/src/lj_err.h +++ b/src/lj_err.h | |||
| @@ -23,7 +23,10 @@ LJ_DATA const char *lj_err_allmsg; | |||
| 23 | LJ_FUNC GCstr *lj_err_str(lua_State *L, ErrMsg em); | 23 | LJ_FUNC GCstr *lj_err_str(lua_State *L, ErrMsg em); |
| 24 | LJ_FUNCA_NORET void LJ_FASTCALL lj_err_throw(lua_State *L, int errcode); | 24 | LJ_FUNCA_NORET void LJ_FASTCALL lj_err_throw(lua_State *L, int errcode); |
| 25 | LJ_FUNC_NORET void lj_err_mem(lua_State *L); | 25 | LJ_FUNC_NORET void lj_err_mem(lua_State *L); |
| 26 | LJ_FUNCA_NORET void LJ_FASTCALL lj_err_run(lua_State *L); | 26 | LJ_FUNC_NORET void LJ_FASTCALL lj_err_run(lua_State *L); |
| 27 | #if LJ_HASJIT | ||
| 28 | LJ_FUNCA_NORET void LJ_FASTCALL lj_err_trace(lua_State *L, int errcode); | ||
| 29 | #endif | ||
| 27 | LJ_FUNC_NORET void lj_err_msg(lua_State *L, ErrMsg em); | 30 | LJ_FUNC_NORET void lj_err_msg(lua_State *L, ErrMsg em); |
| 28 | LJ_FUNC_NORET void lj_err_lex(lua_State *L, GCstr *src, const char *tok, | 31 | LJ_FUNC_NORET void lj_err_lex(lua_State *L, GCstr *src, const char *tok, |
| 29 | BCLine line, ErrMsg em, va_list argp); | 32 | BCLine line, ErrMsg em, va_list argp); |
| @@ -38,4 +41,18 @@ LJ_FUNC_NORET void lj_err_argv(lua_State *L, int narg, ErrMsg em, ...); | |||
| 38 | LJ_FUNC_NORET void lj_err_argtype(lua_State *L, int narg, const char *xname); | 41 | LJ_FUNC_NORET void lj_err_argtype(lua_State *L, int narg, const char *xname); |
| 39 | LJ_FUNC_NORET void lj_err_argt(lua_State *L, int narg, int tt); | 42 | LJ_FUNC_NORET void lj_err_argt(lua_State *L, int narg, int tt); |
| 40 | 43 | ||
| 44 | #if LJ_UNWIND_JIT && !LJ_ABI_WIN | ||
| 45 | LJ_FUNC uint8_t *lj_err_register_mcode(void *base, size_t sz, uint8_t *info); | ||
| 46 | LJ_FUNC void lj_err_deregister_mcode(void *base, size_t sz, uint8_t *info); | ||
| 47 | #else | ||
| 48 | #define lj_err_register_mcode(base, sz, info) (info) | ||
| 49 | #define lj_err_deregister_mcode(base, sz, info) UNUSED(base) | ||
| 50 | #endif | ||
| 51 | |||
| 52 | #if LJ_UNWIND_EXT && !LJ_ABI_WIN && defined(LUA_USE_ASSERT) | ||
| 53 | LJ_FUNC void lj_err_verify(void); | ||
| 54 | #else | ||
| 55 | #define lj_err_verify() ((void)0) | ||
| 56 | #endif | ||
| 57 | |||
| 41 | #endif | 58 | #endif |
diff --git a/src/lj_ffrecord.c b/src/lj_ffrecord.c index 6c7eb2a0..844fc497 100644 --- a/src/lj_ffrecord.c +++ b/src/lj_ffrecord.c | |||
| @@ -455,6 +455,7 @@ static void LJ_FASTCALL recff_pcall(jit_State *J, RecordFFData *rd) | |||
| 455 | #endif | 455 | #endif |
| 456 | lj_record_call(J, 0, J->maxslot - 1); | 456 | lj_record_call(J, 0, J->maxslot - 1); |
| 457 | rd->nres = -1; /* Pending call. */ | 457 | rd->nres = -1; /* Pending call. */ |
| 458 | J->needsnap = 1; /* Start catching on-trace errors. */ | ||
| 458 | } /* else: Interpreter will throw. */ | 459 | } /* else: Interpreter will throw. */ |
| 459 | } | 460 | } |
| 460 | 461 | ||
| @@ -490,6 +491,7 @@ static void LJ_FASTCALL recff_xpcall(jit_State *J, RecordFFData *rd) | |||
| 490 | if (errcode) | 491 | if (errcode) |
| 491 | lj_err_throw(J->L, errcode); /* Propagate errors. */ | 492 | lj_err_throw(J->L, errcode); /* Propagate errors. */ |
| 492 | rd->nres = -1; /* Pending call. */ | 493 | rd->nres = -1; /* Pending call. */ |
| 494 | J->needsnap = 1; /* Start catching on-trace errors. */ | ||
| 493 | } /* else: Interpreter will throw. */ | 495 | } /* else: Interpreter will throw. */ |
| 494 | } | 496 | } |
| 495 | 497 | ||
diff --git a/src/lj_jit.h b/src/lj_jit.h index 03ed3ea0..34ddf907 100644 --- a/src/lj_jit.h +++ b/src/lj_jit.h | |||
| @@ -184,6 +184,7 @@ typedef struct MCLink { | |||
| 184 | typedef struct SnapShot { | 184 | typedef struct SnapShot { |
| 185 | uint32_t mapofs; /* Offset into snapshot map. */ | 185 | uint32_t mapofs; /* Offset into snapshot map. */ |
| 186 | IRRef1 ref; /* First IR ref for this snapshot. */ | 186 | IRRef1 ref; /* First IR ref for this snapshot. */ |
| 187 | uint16_t mcofs; /* Offset into machine code in MCode units. */ | ||
| 187 | uint8_t nslots; /* Number of valid slots. */ | 188 | uint8_t nslots; /* Number of valid slots. */ |
| 188 | uint8_t topslot; /* Maximum frame extent. */ | 189 | uint8_t topslot; /* Maximum frame extent. */ |
| 189 | uint8_t nent; /* Number of compressed entries. */ | 190 | uint8_t nent; /* Number of compressed entries. */ |
| @@ -485,6 +486,7 @@ typedef struct jit_State { | |||
| 485 | const BCIns *startpc; /* Bytecode PC of starting instruction. */ | 486 | const BCIns *startpc; /* Bytecode PC of starting instruction. */ |
| 486 | TraceNo parent; /* Parent of current side trace (0 for root traces). */ | 487 | TraceNo parent; /* Parent of current side trace (0 for root traces). */ |
| 487 | ExitNo exitno; /* Exit number in parent of current side trace. */ | 488 | ExitNo exitno; /* Exit number in parent of current side trace. */ |
| 489 | int exitcode; /* Exit code from unwound trace. */ | ||
| 488 | 490 | ||
| 489 | BCIns *patchpc; /* PC for pending re-patch. */ | 491 | BCIns *patchpc; /* PC for pending re-patch. */ |
| 490 | BCIns patchins; /* Instruction for pending re-patch. */ | 492 | BCIns patchins; /* Instruction for pending re-patch. */ |
diff --git a/src/lj_mcode.c b/src/lj_mcode.c index fc67eaee..b34d7c85 100644 --- a/src/lj_mcode.c +++ b/src/lj_mcode.c | |||
| @@ -269,6 +269,7 @@ static void mcode_allocarea(jit_State *J) | |||
| 269 | ((MCLink *)J->mcarea)->next = oldarea; | 269 | ((MCLink *)J->mcarea)->next = oldarea; |
| 270 | ((MCLink *)J->mcarea)->size = sz; | 270 | ((MCLink *)J->mcarea)->size = sz; |
| 271 | J->szallmcarea += sz; | 271 | J->szallmcarea += sz; |
| 272 | J->mcbot = (MCode *)lj_err_register_mcode(J->mcarea, sz, (uint8_t *)J->mcbot); | ||
| 272 | } | 273 | } |
| 273 | 274 | ||
| 274 | /* Free all MCode areas. */ | 275 | /* Free all MCode areas. */ |
| @@ -279,7 +280,9 @@ void lj_mcode_free(jit_State *J) | |||
| 279 | J->szallmcarea = 0; | 280 | J->szallmcarea = 0; |
| 280 | while (mc) { | 281 | while (mc) { |
| 281 | MCode *next = ((MCLink *)mc)->next; | 282 | MCode *next = ((MCLink *)mc)->next; |
| 282 | mcode_free(J, mc, ((MCLink *)mc)->size); | 283 | size_t sz = ((MCLink *)mc)->size; |
| 284 | lj_err_deregister_mcode(mc, sz, (uint8_t *)mc + sizeof(MCLink)); | ||
| 285 | mcode_free(J, mc, sz); | ||
| 283 | mc = next; | 286 | mc = next; |
| 284 | } | 287 | } |
| 285 | } | 288 | } |
diff --git a/src/lj_opt_loop.c b/src/lj_opt_loop.c index 4c709c63..df5811a9 100644 --- a/src/lj_opt_loop.c +++ b/src/lj_opt_loop.c | |||
| @@ -225,6 +225,7 @@ static void loop_subst_snap(jit_State *J, SnapShot *osnap, | |||
| 225 | /* Setup new snapshot. */ | 225 | /* Setup new snapshot. */ |
| 226 | snap->mapofs = (uint32_t)nmapofs; | 226 | snap->mapofs = (uint32_t)nmapofs; |
| 227 | snap->ref = (IRRef1)J->cur.nins; | 227 | snap->ref = (IRRef1)J->cur.nins; |
| 228 | snap->mcofs = 0; | ||
| 228 | snap->nslots = nslots; | 229 | snap->nslots = nslots; |
| 229 | snap->topslot = osnap->topslot; | 230 | snap->topslot = osnap->topslot; |
| 230 | snap->count = 0; | 231 | snap->count = 0; |
diff --git a/src/lj_record.c b/src/lj_record.c index a4779933..3ca2fb4f 100644 --- a/src/lj_record.c +++ b/src/lj_record.c | |||
| @@ -832,6 +832,7 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) | |||
| 832 | J->base -= cbase; | 832 | J->base -= cbase; |
| 833 | J->base[--rbase] = TREF_TRUE; /* Prepend true to results. */ | 833 | J->base[--rbase] = TREF_TRUE; /* Prepend true to results. */ |
| 834 | frame = frame_prevd(frame); | 834 | frame = frame_prevd(frame); |
| 835 | J->needsnap = 1; /* Stop catching on-trace errors. */ | ||
| 835 | } | 836 | } |
| 836 | /* Return to lower frame via interpreter for unhandled cases. */ | 837 | /* Return to lower frame via interpreter for unhandled cases. */ |
| 837 | if (J->framedepth == 0 && J->pt && bc_isret(bc_op(*J->pc)) && | 838 | if (J->framedepth == 0 && J->pt && bc_isret(bc_op(*J->pc)) && |
| @@ -2050,7 +2051,7 @@ void lj_record_ins(jit_State *J) | |||
| 2050 | /* Need snapshot before recording next bytecode (e.g. after a store). */ | 2051 | /* Need snapshot before recording next bytecode (e.g. after a store). */ |
| 2051 | if (J->needsnap) { | 2052 | if (J->needsnap) { |
| 2052 | J->needsnap = 0; | 2053 | J->needsnap = 0; |
| 2053 | lj_snap_purge(J); | 2054 | if (J->pt) lj_snap_purge(J); |
| 2054 | lj_snap_add(J); | 2055 | lj_snap_add(J); |
| 2055 | J->mergesnap = 1; | 2056 | J->mergesnap = 1; |
| 2056 | } | 2057 | } |
diff --git a/src/lj_snap.c b/src/lj_snap.c index 21f27e1f..fee68ba5 100644 --- a/src/lj_snap.c +++ b/src/lj_snap.c | |||
| @@ -171,6 +171,7 @@ static void snapshot_stack(jit_State *J, SnapShot *snap, MSize nsnapmap) | |||
| 171 | nent += snapshot_framelinks(J, p + nent, &snap->topslot); | 171 | nent += snapshot_framelinks(J, p + nent, &snap->topslot); |
| 172 | snap->mapofs = (uint32_t)nsnapmap; | 172 | snap->mapofs = (uint32_t)nsnapmap; |
| 173 | snap->ref = (IRRef1)J->cur.nins; | 173 | snap->ref = (IRRef1)J->cur.nins; |
| 174 | snap->mcofs = 0; | ||
| 174 | snap->nslots = (uint8_t)nslots; | 175 | snap->nslots = (uint8_t)nslots; |
| 175 | snap->count = 0; | 176 | snap->count = 0; |
| 176 | J->cur.nsnapmap = (uint32_t)(nsnapmap + nent); | 177 | J->cur.nsnapmap = (uint32_t)(nsnapmap + nent); |
diff --git a/src/lj_state.c b/src/lj_state.c index 9585c18a..e87b945a 100644 --- a/src/lj_state.c +++ b/src/lj_state.c | |||
| @@ -156,6 +156,7 @@ static TValue *cpluaopen(lua_State *L, lua_CFunction dummy, void *ud) | |||
| 156 | fixstring(lj_err_str(L, LJ_ERR_ERRMEM)); /* Preallocate memory error msg. */ | 156 | fixstring(lj_err_str(L, LJ_ERR_ERRMEM)); /* Preallocate memory error msg. */ |
| 157 | g->gc.threshold = 4*g->gc.total; | 157 | g->gc.threshold = 4*g->gc.total; |
| 158 | lj_trace_initstate(g); | 158 | lj_trace_initstate(g); |
| 159 | lj_err_verify(); | ||
| 159 | return NULL; | 160 | return NULL; |
| 160 | } | 161 | } |
| 161 | 162 | ||
diff --git a/src/lj_target_x86.h b/src/lj_target_x86.h index 4be5f04c..a403f820 100644 --- a/src/lj_target_x86.h +++ b/src/lj_target_x86.h | |||
| @@ -165,6 +165,8 @@ typedef struct { | |||
| 165 | #define EXITSTUB_SPACING (2+2) | 165 | #define EXITSTUB_SPACING (2+2) |
| 166 | #define EXITSTUBS_PER_GROUP 32 | 166 | #define EXITSTUBS_PER_GROUP 32 |
| 167 | 167 | ||
| 168 | #define EXITTRACE_VMSTATE 1 /* g->vmstate has traceno on exit. */ | ||
| 169 | |||
| 168 | /* -- x86 ModRM operand encoding ------------------------------------------ */ | 170 | /* -- x86 ModRM operand encoding ------------------------------------------ */ |
| 169 | 171 | ||
| 170 | typedef enum { | 172 | typedef enum { |
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 |
diff --git a/src/lj_trace.h b/src/lj_trace.h index 7e86d963..e4cf2dc4 100644 --- a/src/lj_trace.h +++ b/src/lj_trace.h | |||
| @@ -37,6 +37,9 @@ LJ_FUNC void lj_trace_ins(jit_State *J, const BCIns *pc); | |||
| 37 | LJ_FUNCA void LJ_FASTCALL lj_trace_hot(jit_State *J, const BCIns *pc); | 37 | LJ_FUNCA void LJ_FASTCALL lj_trace_hot(jit_State *J, const BCIns *pc); |
| 38 | LJ_FUNCA void LJ_FASTCALL lj_trace_stitch(jit_State *J, const BCIns *pc); | 38 | LJ_FUNCA void LJ_FASTCALL lj_trace_stitch(jit_State *J, const BCIns *pc); |
| 39 | LJ_FUNCA int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr); | 39 | LJ_FUNCA int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr); |
| 40 | #if LJ_UNWIND_EXT | ||
| 41 | LJ_FUNC uintptr_t LJ_FASTCALL lj_trace_unwind(jit_State *J, uintptr_t addr, ExitNo *ep); | ||
| 42 | #endif | ||
| 40 | 43 | ||
| 41 | /* Signal asynchronous abort of trace or end of trace. */ | 44 | /* Signal asynchronous abort of trace or end of trace. */ |
| 42 | #define lj_trace_abort(g) (G2J(g)->state &= ~LJ_TRACE_ACTIVE) | 45 | #define lj_trace_abort(g) (G2J(g)->state &= ~LJ_TRACE_ACTIVE) |
diff --git a/src/lj_vm.h b/src/lj_vm.h index 6358dc58..84348e7a 100644 --- a/src/lj_vm.h +++ b/src/lj_vm.h | |||
| @@ -26,6 +26,9 @@ LJ_ASMF void lj_vm_unwind_ff_eh(void); | |||
| 26 | #if LJ_TARGET_X86ORX64 | 26 | #if LJ_TARGET_X86ORX64 |
| 27 | LJ_ASMF void lj_vm_unwind_rethrow(void); | 27 | LJ_ASMF void lj_vm_unwind_rethrow(void); |
| 28 | #endif | 28 | #endif |
| 29 | #if LJ_TARGET_MIPS | ||
| 30 | LJ_ASMF void lj_vm_unwind_stub(void); | ||
| 31 | #endif | ||
| 29 | 32 | ||
| 30 | /* Miscellaneous functions. */ | 33 | /* Miscellaneous functions. */ |
| 31 | #if LJ_TARGET_X86ORX64 | 34 | #if LJ_TARGET_X86ORX64 |
diff --git a/src/vm_arm.dasc b/src/vm_arm.dasc index 5efda227..c0934ac8 100644 --- a/src/vm_arm.dasc +++ b/src/vm_arm.dasc | |||
| @@ -2245,8 +2245,9 @@ static void build_subroutines(BuildCtx *ctx) | |||
| 2245 | | b <2 | 2245 | | b <2 |
| 2246 | | | 2246 | | |
| 2247 | |9: // Rethrow error from the right C frame. | 2247 | |9: // Rethrow error from the right C frame. |
| 2248 | | rsb CARG2, CARG1, #0 | ||
| 2248 | | mov CARG1, L | 2249 | | mov CARG1, L |
| 2249 | | bl extern lj_err_run // (lua_State *L) | 2250 | | bl extern lj_err_trace // (lua_State *L, int errcode) |
| 2250 | |.endif | 2251 | |.endif |
| 2251 | | | 2252 | | |
| 2252 | |//----------------------------------------------------------------------- | 2253 | |//----------------------------------------------------------------------- |
diff --git a/src/vm_arm64.dasc b/src/vm_arm64.dasc index 755d9a64..3a63d23b 100644 --- a/src/vm_arm64.dasc +++ b/src/vm_arm64.dasc | |||
| @@ -2035,8 +2035,9 @@ static void build_subroutines(BuildCtx *ctx) | |||
| 2035 | | b <2 | 2035 | | b <2 |
| 2036 | | | 2036 | | |
| 2037 | |9: // Rethrow error from the right C frame. | 2037 | |9: // Rethrow error from the right C frame. |
| 2038 | | neg CARG2w, CARG1w | ||
| 2038 | | mov CARG1, L | 2039 | | mov CARG1, L |
| 2039 | | bl extern lj_err_run // (lua_State *L) | 2040 | | bl extern lj_err_trace // (lua_State *L, int errcode) |
| 2040 | |.endif | 2041 | |.endif |
| 2041 | | | 2042 | | |
| 2042 | |//----------------------------------------------------------------------- | 2043 | |//----------------------------------------------------------------------- |
diff --git a/src/vm_mips.dasc b/src/vm_mips.dasc index 7a6a83be..e16066d7 100644 --- a/src/vm_mips.dasc +++ b/src/vm_mips.dasc | |||
| @@ -501,6 +501,10 @@ static void build_subroutines(BuildCtx *ctx) | |||
| 501 | | b ->vm_returnc | 501 | | b ->vm_returnc |
| 502 | |. li RD, 16 // 2 results: false + error message. | 502 | |. li RD, 16 // 2 results: false + error message. |
| 503 | | | 503 | | |
| 504 | |->vm_unwind_stub: // Jump to exit stub from unwinder. | ||
| 505 | | jr CARG1 | ||
| 506 | |. move ra, CARG2 | ||
| 507 | | | ||
| 504 | |//----------------------------------------------------------------------- | 508 | |//----------------------------------------------------------------------- |
| 505 | |//-- Grow stack for calls ----------------------------------------------- | 509 | |//-- Grow stack for calls ----------------------------------------------- |
| 506 | |//----------------------------------------------------------------------- | 510 | |//----------------------------------------------------------------------- |
| @@ -2520,8 +2524,9 @@ static void build_subroutines(BuildCtx *ctx) | |||
| 2520 | |. addu RA, RA, BASE | 2524 | |. addu RA, RA, BASE |
| 2521 | | | 2525 | | |
| 2522 | |9: // Rethrow error from the right C frame. | 2526 | |9: // Rethrow error from the right C frame. |
| 2523 | | load_got lj_err_run | 2527 | | load_got lj_err_trace |
| 2524 | | call_intern lj_err_run // (lua_State *L) | 2528 | | sub CARG2, r0, CRET1 |
| 2529 | | call_intern lj_err_trace // (lua_State *L, int errcode) | ||
| 2525 | |. move CARG1, L | 2530 | |. move CARG1, L |
| 2526 | |.endif | 2531 | |.endif |
| 2527 | | | 2532 | | |
diff --git a/src/vm_mips64.dasc b/src/vm_mips64.dasc index 0b642095..877d9885 100644 --- a/src/vm_mips64.dasc +++ b/src/vm_mips64.dasc | |||
| @@ -556,6 +556,10 @@ static void build_subroutines(BuildCtx *ctx) | |||
| 556 | | b ->vm_returnc | 556 | | b ->vm_returnc |
| 557 | |. li RD, 16 // 2 results: false + error message. | 557 | |. li RD, 16 // 2 results: false + error message. |
| 558 | | | 558 | | |
| 559 | |->vm_unwind_stub: // Jump to exit stub from unwinder. | ||
| 560 | | jr CARG1 | ||
| 561 | |. move ra, CARG2 | ||
| 562 | | | ||
| 559 | |//----------------------------------------------------------------------- | 563 | |//----------------------------------------------------------------------- |
| 560 | |//-- Grow stack for calls ----------------------------------------------- | 564 | |//-- Grow stack for calls ----------------------------------------------- |
| 561 | |//----------------------------------------------------------------------- | 565 | |//----------------------------------------------------------------------- |
| @@ -2622,8 +2626,9 @@ static void build_subroutines(BuildCtx *ctx) | |||
| 2622 | |. daddu RA, RA, BASE | 2626 | |. daddu RA, RA, BASE |
| 2623 | | | 2627 | | |
| 2624 | |9: // Rethrow error from the right C frame. | 2628 | |9: // Rethrow error from the right C frame. |
| 2625 | | load_got lj_err_run | 2629 | | load_got lj_err_trace |
| 2626 | | call_intern lj_err_run // (lua_State *L) | 2630 | | sub CARG2, r0, CRET1 |
| 2631 | | call_intern lj_err_trace // (lua_State *L, int errcode) | ||
| 2627 | |. move CARG1, L | 2632 | |. move CARG1, L |
| 2628 | |.endif | 2633 | |.endif |
| 2629 | | | 2634 | | |
diff --git a/src/vm_ppc.dasc b/src/vm_ppc.dasc index f4ebb9db..1cd8eb15 100644 --- a/src/vm_ppc.dasc +++ b/src/vm_ppc.dasc | |||
| @@ -3090,8 +3090,9 @@ static void build_subroutines(BuildCtx *ctx) | |||
| 3090 | | bctr | 3090 | | bctr |
| 3091 | | | 3091 | | |
| 3092 | |9: // Rethrow error from the right C frame. | 3092 | |9: // Rethrow error from the right C frame. |
| 3093 | | neg CARG2, CARG1 | ||
| 3093 | | mr CARG1, L | 3094 | | mr CARG1, L |
| 3094 | | bl extern lj_err_run // (lua_State *L) | 3095 | | bl extern lj_err_trace // (lua_State *L, int errcode) |
| 3095 | |.endif | 3096 | |.endif |
| 3096 | | | 3097 | | |
| 3097 | |//----------------------------------------------------------------------- | 3098 | |//----------------------------------------------------------------------- |
diff --git a/src/vm_x64.dasc b/src/vm_x64.dasc index 8ade0a6a..05bfa649 100644 --- a/src/vm_x64.dasc +++ b/src/vm_x64.dasc | |||
| @@ -2509,8 +2509,10 @@ static void build_subroutines(BuildCtx *ctx) | |||
| 2509 | | jmp <2 | 2509 | | jmp <2 |
| 2510 | | | 2510 | | |
| 2511 | |9: // Rethrow error from the right C frame. | 2511 | |9: // Rethrow error from the right C frame. |
| 2512 | | mov CARG2d, RDd | ||
| 2512 | | mov CARG1, L:RB | 2513 | | mov CARG1, L:RB |
| 2513 | | call extern lj_err_run // (lua_State *L) | 2514 | | neg CARG2d |
| 2515 | | call extern lj_err_trace // (lua_State *L, int errcode) | ||
| 2514 | |.endif | 2516 | |.endif |
| 2515 | | | 2517 | | |
| 2516 | |//----------------------------------------------------------------------- | 2518 | |//----------------------------------------------------------------------- |
diff --git a/src/vm_x86.dasc b/src/vm_x86.dasc index 1fee4a2a..1e376e45 100644 --- a/src/vm_x86.dasc +++ b/src/vm_x86.dasc | |||
| @@ -2964,8 +2964,10 @@ static void build_subroutines(BuildCtx *ctx) | |||
| 2964 | | jmp <2 | 2964 | | jmp <2 |
| 2965 | | | 2965 | | |
| 2966 | |9: // Rethrow error from the right C frame. | 2966 | |9: // Rethrow error from the right C frame. |
| 2967 | | mov FCARG2, RD | ||
| 2967 | | mov FCARG1, L:RB | 2968 | | mov FCARG1, L:RB |
| 2968 | | call extern lj_err_run@4 // (lua_State *L) | 2969 | | neg FCARG2 |
| 2970 | | call extern lj_err_trace@8 // (lua_State *L, int errcode) | ||
| 2969 | |.endif | 2971 | |.endif |
| 2970 | | | 2972 | | |
| 2971 | |//----------------------------------------------------------------------- | 2973 | |//----------------------------------------------------------------------- |
