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.c95
1 files changed, 71 insertions, 24 deletions
diff --git a/src/lj_asm.c b/src/lj_asm.c
index 5e38d254..5235dd00 100644
--- a/src/lj_asm.c
+++ b/src/lj_asm.c
@@ -625,9 +625,8 @@ static void ra_addrename(ASMState *as, Reg down, IRRef ref, SnapNo snapno)
625 IRRef ren; 625 IRRef ren;
626 lj_ir_set(as->J, IRT(IR_RENAME, IRT_NIL), ref, snapno); 626 lj_ir_set(as->J, IRT(IR_RENAME, IRT_NIL), ref, snapno);
627 ren = tref_ref(lj_ir_emit(as->J)); 627 ren = tref_ref(lj_ir_emit(as->J));
628 as->ir = as->T->ir; /* The IR may have been reallocated. */ 628 as->J->cur.ir[ren].r = (uint8_t)down;
629 IR(ren)->r = (uint8_t)down; 629 as->J->cur.ir[ren].s = SPS_NONE;
630 IR(ren)->s = SPS_NONE;
631} 630}
632 631
633/* Rename register allocation and emit move. */ 632/* Rename register allocation and emit move. */
@@ -948,7 +947,7 @@ static void asm_snap_prep(ASMState *as)
948 } else { 947 } else {
949 /* Process any renames above the highwater mark. */ 948 /* Process any renames above the highwater mark. */
950 for (; as->snaprename < as->T->nins; as->snaprename++) { 949 for (; as->snaprename < as->T->nins; as->snaprename++) {
951 IRIns *ir = IR(as->snaprename); 950 IRIns *ir = &as->T->ir[as->snaprename];
952 if (asm_snap_checkrename(as, ir->op1)) 951 if (asm_snap_checkrename(as, ir->op1))
953 ir->op2 = REF_BIAS-1; /* Kill rename. */ 952 ir->op2 = REF_BIAS-1; /* Kill rename. */
954 } 953 }
@@ -1967,8 +1966,9 @@ static void asm_setup_regsp(ASMState *as)
1967 1966
1968 ir = IR(nins-1); 1967 ir = IR(nins-1);
1969 if (ir->o == IR_RENAME) { 1968 if (ir->o == IR_RENAME) {
1969 /* Remove any renames left over from ASM restart due to LJ_TRERR_MCODELM. */
1970 do { ir--; nins--; } while (ir->o == IR_RENAME); 1970 do { ir--; nins--; } while (ir->o == IR_RENAME);
1971 T->nins = nins; /* Remove any renames left over from ASM restart. */ 1971 T->nins = nins;
1972 } 1972 }
1973 as->snaprename = nins; 1973 as->snaprename = nins;
1974 as->snapref = nins; 1974 as->snapref = nins;
@@ -2202,13 +2202,14 @@ void lj_asm_trace(jit_State *J, GCtrace *T)
2202 MCode *origtop; 2202 MCode *origtop;
2203 2203
2204 /* Ensure an initialized instruction beyond the last one for HIOP checks. */ 2204 /* Ensure an initialized instruction beyond the last one for HIOP checks. */
2205 J->cur.nins = lj_ir_nextins(J); 2205 /* This also allows one RENAME to be added without reallocating curfinal. */
2206 J->cur.ir[J->cur.nins].o = IR_NOP; 2206 as->orignins = lj_ir_nextins(J);
2207 J->cur.ir[as->orignins].o = IR_NOP;
2207 2208
2208 /* Setup initial state. Copy some fields to reduce indirections. */ 2209 /* Setup initial state. Copy some fields to reduce indirections. */
2209 as->J = J; 2210 as->J = J;
2210 as->T = T; 2211 as->T = T;
2211 as->ir = T->ir; 2212 J->curfinal = lj_trace_alloc(J->L, T); /* This copies the IR, too. */
2212 as->flags = J->flags; 2213 as->flags = J->flags;
2213 as->loopref = J->loopref; 2214 as->loopref = J->loopref;
2214 as->realign = NULL; 2215 as->realign = NULL;
@@ -2221,12 +2222,41 @@ void lj_asm_trace(jit_State *J, GCtrace *T)
2221 as->mclim = as->mcbot + MCLIM_REDZONE; 2222 as->mclim = as->mcbot + MCLIM_REDZONE;
2222 asm_setup_target(as); 2223 asm_setup_target(as);
2223 2224
2224 do { 2225 /*
2226 ** This is a loop, because the MCode may have to be (re-)assembled
2227 ** multiple times:
2228 **
2229 ** 1. as->realign is set (and the assembly aborted), if the arch-specific
2230 ** backend wants the MCode to be aligned differently.
2231 **
2232 ** This is currently only the case on x86/x64, where small loops get
2233 ** an aligned loop body plus a short branch. Not much effort is wasted,
2234 ** because the abort happens very quickly and only once.
2235 **
2236 ** 2. The IR is immovable, since the MCode embeds pointers to various
2237 ** constants inside the IR. But RENAMEs may need to be added to the IR
2238 ** during assembly, which might grow and reallocate the IR. We check
2239 ** at the end if the IR (in J->cur.ir) has actually grown, resize the
2240 ** copy (in J->curfinal.ir) and try again.
2241 **
2242 ** 95% of all traces have zero RENAMEs, 3% have one RENAME, 1.5% have
2243 ** 2 RENAMEs and only 0.5% have more than that. That's why we opt to
2244 ** always have one spare slot in the IR (see above), which means we
2245 ** have to redo the assembly for only ~2% of all traces.
2246 **
2247 ** Very, very rarely, this needs to be done repeatedly, since the
2248 ** location of constants inside the IR (actually, reachability from
2249 ** a global pointer) may affect register allocation and thus the
2250 ** number of RENAMEs.
2251 */
2252 for (;;) {
2225 as->mcp = as->mctop; 2253 as->mcp = as->mctop;
2226#ifdef LUA_USE_ASSERT 2254#ifdef LUA_USE_ASSERT
2227 as->mcp_prev = as->mcp; 2255 as->mcp_prev = as->mcp;
2228#endif 2256#endif
2229 as->curins = T->nins; 2257 as->ir = J->curfinal->ir; /* Use the copied IR. */
2258 as->curins = J->cur.nins = as->orignins;
2259
2230 RA_DBG_START(); 2260 RA_DBG_START();
2231 RA_DBGX((as, "===== STOP =====")); 2261 RA_DBGX((as, "===== STOP ====="));
2232 2262
@@ -2254,22 +2284,39 @@ void lj_asm_trace(jit_State *J, GCtrace *T)
2254 checkmclim(as); 2284 checkmclim(as);
2255 asm_ir(as, ir); 2285 asm_ir(as, ir);
2256 } 2286 }
2257 } while (as->realign); /* Retry in case the MCode needs to be realigned. */
2258 2287
2259 /* Emit head of trace. */ 2288 if (as->realign && J->curfinal->nins >= T->nins)
2260 RA_DBG_REF(); 2289 continue; /* Retry in case only the MCode needs to be realigned. */
2261 checkmclim(as); 2290
2262 if (as->gcsteps > 0) { 2291 /* Emit head of trace. */
2263 as->curins = as->T->snap[0].ref; 2292 RA_DBG_REF();
2264 asm_snap_prep(as); /* The GC check is a guard. */ 2293 checkmclim(as);
2265 asm_gc_check(as); 2294 if (as->gcsteps > 0) {
2295 as->curins = as->T->snap[0].ref;
2296 asm_snap_prep(as); /* The GC check is a guard. */
2297 asm_gc_check(as);
2298 }
2299 ra_evictk(as);
2300 if (as->parent)
2301 asm_head_side(as);
2302 else
2303 asm_head_root(as);
2304 asm_phi_fixup(as);
2305
2306 if (J->curfinal->nins >= T->nins) { /* IR didn't grow? */
2307 lua_assert(J->curfinal->nk == T->nk);
2308 memcpy(J->curfinal->ir + as->orignins, T->ir + as->orignins,
2309 (T->nins - as->orignins) * sizeof(IRIns)); /* Copy RENAMEs. */
2310 T->nins = J->curfinal->nins;
2311 break; /* Done. */
2312 }
2313
2314 /* Otherwise try again with a bigger IR. */
2315 lj_trace_free(J2G(J), J->curfinal);
2316 J->curfinal = NULL; /* In case lj_trace_alloc() OOMs. */
2317 J->curfinal = lj_trace_alloc(J->L, T);
2318 as->realign = NULL;
2266 } 2319 }
2267 ra_evictk(as);
2268 if (as->parent)
2269 asm_head_side(as);
2270 else
2271 asm_head_root(as);
2272 asm_phi_fixup(as);
2273 2320
2274 RA_DBGX((as, "===== START ====")); 2321 RA_DBGX((as, "===== START ===="));
2275 RA_DBG_FLUSH(); 2322 RA_DBG_FLUSH();