aboutsummaryrefslogtreecommitdiff
path: root/src/lj_opt_loop.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_opt_loop.c')
-rw-r--r--src/lj_opt_loop.c45
1 files changed, 31 insertions, 14 deletions
diff --git a/src/lj_opt_loop.c b/src/lj_opt_loop.c
index 466f88de..ee3ee049 100644
--- a/src/lj_opt_loop.c
+++ b/src/lj_opt_loop.c
@@ -11,7 +11,7 @@
11#if LJ_HASJIT 11#if LJ_HASJIT
12 12
13#include "lj_err.h" 13#include "lj_err.h"
14#include "lj_str.h" 14#include "lj_buf.h"
15#include "lj_ir.h" 15#include "lj_ir.h"
16#include "lj_jit.h" 16#include "lj_jit.h"
17#include "lj_iropt.h" 17#include "lj_iropt.h"
@@ -225,6 +225,7 @@ static void loop_subst_snap(jit_State *J, SnapShot *osnap,
225 /* Setup new snapshot. */ 225 /* Setup new snapshot. */
226 snap->mapofs = (uint32_t)nmapofs; 226 snap->mapofs = (uint32_t)nmapofs;
227 snap->ref = (IRRef1)J->cur.nins; 227 snap->ref = (IRRef1)J->cur.nins;
228 snap->mcofs = 0;
228 snap->nslots = nslots; 229 snap->nslots = nslots;
229 snap->topslot = osnap->topslot; 230 snap->topslot = osnap->topslot;
230 snap->count = 0; 231 snap->count = 0;
@@ -254,9 +255,16 @@ static void loop_subst_snap(jit_State *J, SnapShot *osnap,
254 J->cur.nsnapmap = (uint32_t)(nmap - J->cur.snapmap); 255 J->cur.nsnapmap = (uint32_t)(nmap - J->cur.snapmap);
255} 256}
256 257
258typedef struct LoopState {
259 jit_State *J;
260 IRRef1 *subst;
261 MSize sizesubst;
262} LoopState;
263
257/* Unroll loop. */ 264/* Unroll loop. */
258static void loop_unroll(jit_State *J) 265static void loop_unroll(LoopState *lps)
259{ 266{
267 jit_State *J = lps->J;
260 IRRef1 phi[LJ_MAX_PHI]; 268 IRRef1 phi[LJ_MAX_PHI];
261 uint32_t nphi = 0; 269 uint32_t nphi = 0;
262 IRRef1 *subst; 270 IRRef1 *subst;
@@ -265,13 +273,13 @@ static void loop_unroll(jit_State *J)
265 SnapEntry *loopmap, *psentinel; 273 SnapEntry *loopmap, *psentinel;
266 IRRef ins, invar; 274 IRRef ins, invar;
267 275
268 /* Use temp buffer for substitution table. 276 /* Allocate substitution table.
269 ** Only non-constant refs in [REF_BIAS,invar) are valid indexes. 277 ** Only non-constant refs in [REF_BIAS,invar) are valid indexes.
270 ** Caveat: don't call into the VM or run the GC or the buffer may be gone.
271 */ 278 */
272 invar = J->cur.nins; 279 invar = J->cur.nins;
273 subst = (IRRef1 *)lj_str_needbuf(J->L, &G(J->L)->tmpbuf, 280 lps->sizesubst = invar - REF_BIAS;
274 (invar-REF_BIAS)*sizeof(IRRef1)) - REF_BIAS; 281 lps->subst = lj_mem_newvec(J->L, lps->sizesubst, IRRef1);
282 subst = lps->subst - REF_BIAS;
275 subst[REF_BASE] = REF_BASE; 283 subst[REF_BASE] = REF_BASE;
276 284
277 /* LOOP separates the pre-roll from the loop body. */ 285 /* LOOP separates the pre-roll from the loop body. */
@@ -292,7 +300,8 @@ static void loop_unroll(jit_State *J)
292 loopmap = &J->cur.snapmap[loopsnap->mapofs]; 300 loopmap = &J->cur.snapmap[loopsnap->mapofs];
293 /* The PC of snapshot #0 and the loop snapshot must match. */ 301 /* The PC of snapshot #0 and the loop snapshot must match. */
294 psentinel = &loopmap[loopsnap->nent]; 302 psentinel = &loopmap[loopsnap->nent];
295 lua_assert(*psentinel == J->cur.snapmap[J->cur.snap[0].nent]); 303 lj_assertJ(*psentinel == J->cur.snapmap[J->cur.snap[0].nent],
304 "mismatched PC for loop snapshot");
296 *psentinel = SNAP(255, 0, 0); /* Replace PC with temporary sentinel. */ 305 *psentinel = SNAP(255, 0, 0); /* Replace PC with temporary sentinel. */
297 306
298 /* Start substitution with snapshot #1 (#0 is empty for root traces). */ 307 /* Start substitution with snapshot #1 (#0 is empty for root traces). */
@@ -345,10 +354,12 @@ static void loop_unroll(jit_State *J)
345 irr = IR(ref); 354 irr = IR(ref);
346 goto phiconv; 355 goto phiconv;
347 } 356 }
348 } else if (ref != REF_DROP && irr->o == IR_CONV && 357 } else if (ref != REF_DROP && ref > invar &&
349 ref > invar && irr->op1 < invar) { 358 ((irr->o == IR_CONV && irr->op1 < invar) ||
350 /* May need an extra PHI for a CONV. */ 359 (irr->o == IR_ALEN && irr->op2 < invar &&
351 ref = irr->op1; 360 irr->op2 != REF_NIL))) {
361 /* May need an extra PHI for a CONV or ALEN hint. */
362 ref = irr->o == IR_CONV ? irr->op1 : irr->op2;
352 irr = IR(ref); 363 irr = IR(ref);
353 phiconv: 364 phiconv:
354 if (ref < invar && !irref_isk(ref) && !irt_isphi(irr->t)) { 365 if (ref < invar && !irref_isk(ref) && !irt_isphi(irr->t)) {
@@ -363,7 +374,7 @@ static void loop_unroll(jit_State *J)
363 } 374 }
364 if (!irt_isguard(J->guardemit)) /* Drop redundant snapshot. */ 375 if (!irt_isguard(J->guardemit)) /* Drop redundant snapshot. */
365 J->cur.nsnapmap = (uint32_t)J->cur.snap[--J->cur.nsnap].mapofs; 376 J->cur.nsnapmap = (uint32_t)J->cur.snap[--J->cur.nsnap].mapofs;
366 lua_assert(J->cur.nsnapmap <= J->sizesnapmap); 377 lj_assertJ(J->cur.nsnapmap <= J->sizesnapmap, "bad snapshot map index");
367 *psentinel = J->cur.snapmap[J->cur.snap[0].nent]; /* Restore PC. */ 378 *psentinel = J->cur.snapmap[J->cur.snap[0].nent]; /* Restore PC. */
368 379
369 loop_emit_phi(J, subst, phi, nphi, onsnap); 380 loop_emit_phi(J, subst, phi, nphi, onsnap);
@@ -396,7 +407,7 @@ static void loop_undo(jit_State *J, IRRef ins, SnapNo nsnap, MSize nsnapmap)
396static TValue *cploop_opt(lua_State *L, lua_CFunction dummy, void *ud) 407static TValue *cploop_opt(lua_State *L, lua_CFunction dummy, void *ud)
397{ 408{
398 UNUSED(L); UNUSED(dummy); 409 UNUSED(L); UNUSED(dummy);
399 loop_unroll((jit_State *)ud); 410 loop_unroll((LoopState *)ud);
400 return NULL; 411 return NULL;
401} 412}
402 413
@@ -406,7 +417,13 @@ int lj_opt_loop(jit_State *J)
406 IRRef nins = J->cur.nins; 417 IRRef nins = J->cur.nins;
407 SnapNo nsnap = J->cur.nsnap; 418 SnapNo nsnap = J->cur.nsnap;
408 MSize nsnapmap = J->cur.nsnapmap; 419 MSize nsnapmap = J->cur.nsnapmap;
409 int errcode = lj_vm_cpcall(J->L, NULL, J, cploop_opt); 420 LoopState lps;
421 int errcode;
422 lps.J = J;
423 lps.subst = NULL;
424 lps.sizesubst = 0;
425 errcode = lj_vm_cpcall(J->L, NULL, &lps, cploop_opt);
426 lj_mem_freevec(J2G(J), lps.subst, lps.sizesubst, IRRef1);
410 if (LJ_UNLIKELY(errcode)) { 427 if (LJ_UNLIKELY(errcode)) {
411 lua_State *L = J->L; 428 lua_State *L = J->L;
412 if (errcode == LUA_ERRRUN && tvisnumber(L->top-1)) { /* Trace error? */ 429 if (errcode == LUA_ERRRUN && tvisnumber(L->top-1)) { /* Trace error? */