diff options
Diffstat (limited to 'src/lj_opt_fold.c')
-rw-r--r-- | src/lj_opt_fold.c | 47 |
1 files changed, 38 insertions, 9 deletions
diff --git a/src/lj_opt_fold.c b/src/lj_opt_fold.c index 743dfb07..ce78505b 100644 --- a/src/lj_opt_fold.c +++ b/src/lj_opt_fold.c | |||
@@ -2134,8 +2134,26 @@ LJFOLDX(lj_opt_fwd_uload) | |||
2134 | LJFOLD(ALEN any any) | 2134 | LJFOLD(ALEN any any) |
2135 | LJFOLDX(lj_opt_fwd_alen) | 2135 | LJFOLDX(lj_opt_fwd_alen) |
2136 | 2136 | ||
2137 | /* Try to merge UREFO/UREFC into referenced instruction. */ | ||
2138 | static TRef merge_uref(jit_State *J, IRRef ref, IRIns* ir) | ||
2139 | { | ||
2140 | if (ir->o == IR_UREFO && irt_isguard(ir->t)) { | ||
2141 | /* Might be pointing to some other coroutine's stack. | ||
2142 | ** And GC might shrink said stack, thereby repointing the upvalue. | ||
2143 | ** GC might even collect said coroutine, thereby closing the upvalue. | ||
2144 | */ | ||
2145 | if (gcstep_barrier(J, ref)) | ||
2146 | return EMITFOLD; /* So cannot merge. */ | ||
2147 | /* Current fins wants a check, but ir doesn't have one. */ | ||
2148 | if ((irt_t(fins->t) & (IRT_GUARD|IRT_TYPE)) == (IRT_GUARD|IRT_PGC) && | ||
2149 | irt_type(ir->t) == IRT_IGC) | ||
2150 | ir->t.irt += IRT_PGC-IRT_IGC; /* So install a check. */ | ||
2151 | } | ||
2152 | return ref; /* Not a TRef, but the caller doesn't care. */ | ||
2153 | } | ||
2154 | |||
2137 | /* Upvalue refs are really loads, but there are no corresponding stores. | 2155 | /* Upvalue refs are really loads, but there are no corresponding stores. |
2138 | ** So CSE is ok for them, except for UREFO across a GC step (see below). | 2156 | ** So CSE is ok for them, except for guarded UREFO across a GC step. |
2139 | ** If the referenced function is const, its upvalue addresses are const, too. | 2157 | ** If the referenced function is const, its upvalue addresses are const, too. |
2140 | ** This can be used to improve CSE by looking for the same address, | 2158 | ** This can be used to improve CSE by looking for the same address, |
2141 | ** even if the upvalues originate from a different function. | 2159 | ** even if the upvalues originate from a different function. |
@@ -2153,9 +2171,7 @@ LJFOLDF(cse_uref) | |||
2153 | if (irref_isk(ir->op1)) { | 2171 | if (irref_isk(ir->op1)) { |
2154 | GCfunc *fn2 = ir_kfunc(IR(ir->op1)); | 2172 | GCfunc *fn2 = ir_kfunc(IR(ir->op1)); |
2155 | if (gco2uv(gcref(fn2->l.uvptr[(ir->op2 >> 8)])) == uv) { | 2173 | if (gco2uv(gcref(fn2->l.uvptr[(ir->op2 >> 8)])) == uv) { |
2156 | if (fins->o == IR_UREFO && gcstep_barrier(J, ref)) | 2174 | return merge_uref(J, ref, ir); |
2157 | break; | ||
2158 | return ref; | ||
2159 | } | 2175 | } |
2160 | } | 2176 | } |
2161 | ref = ir->prev; | 2177 | ref = ir->prev; |
@@ -2164,6 +2180,24 @@ LJFOLDF(cse_uref) | |||
2164 | return EMITFOLD; | 2180 | return EMITFOLD; |
2165 | } | 2181 | } |
2166 | 2182 | ||
2183 | /* Custom CSE for UREFO. */ | ||
2184 | LJFOLD(UREFO any any) | ||
2185 | LJFOLDF(cse_urefo) | ||
2186 | { | ||
2187 | if (LJ_LIKELY(J->flags & JIT_F_OPT_CSE)) { | ||
2188 | IRRef ref = J->chain[IR_UREFO]; | ||
2189 | IRRef lim = fins->op1; | ||
2190 | IRRef2 op12 = (IRRef2)fins->op1 + ((IRRef2)fins->op2 << 16); | ||
2191 | while (ref > lim) { | ||
2192 | IRIns *ir = IR(ref); | ||
2193 | if (ir->op12 == op12) | ||
2194 | return merge_uref(J, ref, ir); | ||
2195 | ref = ir->prev; | ||
2196 | } | ||
2197 | } | ||
2198 | return EMITFOLD; | ||
2199 | } | ||
2200 | |||
2167 | LJFOLD(HREFK any any) | 2201 | LJFOLD(HREFK any any) |
2168 | LJFOLDX(lj_opt_fwd_hrefk) | 2202 | LJFOLDX(lj_opt_fwd_hrefk) |
2169 | 2203 | ||
@@ -2384,14 +2418,9 @@ LJFOLDF(fold_base) | |||
2384 | 2418 | ||
2385 | /* Write barriers are amenable to CSE, but not across any incremental | 2419 | /* Write barriers are amenable to CSE, but not across any incremental |
2386 | ** GC steps. | 2420 | ** GC steps. |
2387 | ** | ||
2388 | ** The same logic applies to open upvalue references, because a stack | ||
2389 | ** may be resized during a GC step (not the current stack, but maybe that | ||
2390 | ** of a coroutine). | ||
2391 | */ | 2421 | */ |
2392 | LJFOLD(TBAR any) | 2422 | LJFOLD(TBAR any) |
2393 | LJFOLD(OBAR any any) | 2423 | LJFOLD(OBAR any any) |
2394 | LJFOLD(UREFO any any) | ||
2395 | LJFOLDF(barrier_tab) | 2424 | LJFOLDF(barrier_tab) |
2396 | { | 2425 | { |
2397 | TRef tr = lj_opt_cse(J); | 2426 | TRef tr = lj_opt_cse(J); |