aboutsummaryrefslogtreecommitdiff
path: root/src/lj_asm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_asm.c')
-rw-r--r--src/lj_asm.c71
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. */
950static void asm_snap_alloc(ASMState *as) 952static 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. */
996static void asm_snap_prep(ASMState *as) 998static 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. */
1016static 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. */
1032static 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