diff options
Diffstat (limited to 'src/lj_asm.c')
-rw-r--r-- | src/lj_asm.c | 95 |
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(); |