diff options
Diffstat (limited to 'src/lj_asm.c')
-rw-r--r-- | src/lj_asm.c | 71 |
1 files changed, 54 insertions, 17 deletions
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 |