Eliminate redundant stack checks. Add checks for growing root traces.

This commit is contained in:
Mike Pall 2010-02-21 16:47:43 +01:00
parent c52da1f2da
commit c1658ddcf1
2 changed files with 26 additions and 8 deletions

View File

@ -2840,19 +2840,24 @@ static void asm_head_root(ASMState *as)
spadj = sps_adjust(as->evenspill); spadj = sps_adjust(as->evenspill);
as->T->spadjust = (uint16_t)spadj; as->T->spadjust = (uint16_t)spadj;
emit_addptr(as, RID_ESP, -spadj); emit_addptr(as, RID_ESP, -spadj);
/* Root traces assume a checked stack for the starting proto. */
as->T->topslot = gcref(as->T->startpt)->pt.framesize;
} }
/* Check Lua stack size for overflow at the start of a side trace. /* Check Lua stack size for overflow at the start of a side trace.
** Stack overflow is rare, so let the regular exit handling fix this up. ** Stack overflow is rare, so let the regular exit handling fix this up.
** This is done in the context of the *parent* trace and parent exitno! ** This is done in the context of the *parent* trace and parent exitno!
*/ */
static void asm_checkstack(ASMState *as, BCReg topslot, Reg pbase, RegSet allow) static void asm_checkstack(ASMState *as, BCReg topslot,
Reg pbase, RegSet allow, ExitNo exitno)
{ {
/* Try to get an unused temp. register, otherwise spill/restore eax. */ /* Try to get an unused temp. register, otherwise spill/restore eax. */
Reg r = allow ? rset_pickbot(allow) : RID_EAX; Reg r = allow ? rset_pickbot(allow) : RID_EAX;
emit_jcc(as, CC_B, exitstub_addr(as->J, as->J->exitno)); emit_jcc(as, CC_B, exitstub_addr(as->J, exitno));
if (allow == RSET_EMPTY) /* Restore temp. register. */ if (allow == RSET_EMPTY) /* Restore temp. register. */
emit_rmro(as, XO_MOV, r, RID_ESP, sps_scale(SPS_TEMP1)); emit_rmro(as, XO_MOV, r, RID_ESP, sps_scale(SPS_TEMP1));
else
ra_modified(as, r);
emit_gri(as, XG_ARITHi(XOg_CMP), r, (int32_t)(8*topslot)); emit_gri(as, XG_ARITHi(XOg_CMP), r, (int32_t)(8*topslot));
if (ra_hasreg(pbase) && pbase != r) if (ra_hasreg(pbase) && pbase != r)
emit_rr(as, XO_ARITH(XOg_SUB), r, pbase); emit_rr(as, XO_ARITH(XOg_SUB), r, pbase);
@ -3029,9 +3034,13 @@ static void asm_head_side(ASMState *as)
/* Continue with coalescing to fix up the broken cycle(s). */ /* Continue with coalescing to fix up the broken cycle(s). */
} }
/* Check Lua stack size if frames have been added. */ /* Inherit top stack slot already checked by parent trace. */
if (as->topslot) as->T->topslot = as->parent->topslot;
asm_checkstack(as, as->topslot, pbase, allow & RSET_GPR); if (as->topslot > as->T->topslot) { /* Need to check for higher slot? */
as->T->topslot = (uint8_t)as->topslot; /* Remember for child traces. */
/* Reuse the parent exit in the context of the parent trace. */
asm_checkstack(as, as->topslot, pbase, allow & RSET_GPR, as->J->exitno);
}
} }
/* -- Tail of trace ------------------------------------------------------- */ /* -- Tail of trace ------------------------------------------------------- */
@ -3041,7 +3050,8 @@ static void asm_head_side(ASMState *as)
*/ */
static void asm_tail_sync(ASMState *as) static void asm_tail_sync(ASMState *as)
{ {
SnapShot *snap = &as->T->snap[as->T->nsnap-1]; /* Last snapshot. */ SnapNo snapno = as->T->nsnap-1; /* Last snapshot. */
SnapShot *snap = &as->T->snap[snapno];
MSize n, nent = snap->nent; MSize n, nent = snap->nent;
SnapEntry *map = &as->T->snapmap[snap->mapofs]; SnapEntry *map = &as->T->snapmap[snap->mapofs];
SnapEntry *flinks = map + nent + snap->depth; SnapEntry *flinks = map + nent + snap->depth;
@ -3107,6 +3117,10 @@ static void asm_tail_sync(ASMState *as)
checkmclim(as); checkmclim(as);
} }
lua_assert(map + nent == flinks); lua_assert(map + nent == flinks);
/* Root traces that grow the stack need to check the stack at the end. */
if (!as->parent && topslot)
asm_checkstack(as, topslot, RID_BASE, as->freeset & RSET_GPR, snapno);
} }
/* Fixup the tail code. */ /* Fixup the tail code. */
@ -3479,7 +3493,7 @@ void lj_asm_trace(jit_State *J, Trace *T)
if (as->gcsteps) if (as->gcsteps)
asm_gc_check(as, &as->T->snap[0]); asm_gc_check(as, &as->T->snap[0]);
asm_const_remat(as); asm_const_remat(as);
if (J->parent) if (as->parent)
asm_head_side(as); asm_head_side(as);
else else
asm_head_root(as); asm_head_root(as);

View File

@ -169,6 +169,10 @@ typedef struct Trace {
TraceNo1 nextside; /* Next side trace of same root trace. */ TraceNo1 nextside; /* Next side trace of same root trace. */
uint16_t nchild; /* Number of child traces (root trace only). */ uint16_t nchild; /* Number of child traces (root trace only). */
uint16_t spadjust; /* Stack pointer adjustment (offset in bytes). */ uint16_t spadjust; /* Stack pointer adjustment (offset in bytes). */
uint8_t topslot; /* Top stack slot already checked to be allocated. */
uint8_t unused1;
uint8_t unused2;
uint8_t unused3;
#ifdef LUAJIT_USE_GDBJIT #ifdef LUAJIT_USE_GDBJIT
void *gdbjit_entry; /* GDB JIT entry. */ void *gdbjit_entry; /* GDB JIT entry. */
#endif #endif
@ -227,9 +231,9 @@ typedef struct jit_State {
TraceState state; /* Trace compiler state. */ TraceState state; /* Trace compiler state. */
uint64_t tailcalled; /* History of the number of successive tailcalls. */
int32_t instunroll; /* Unroll counter for instable loops. */ int32_t instunroll; /* Unroll counter for instable loops. */
int32_t loopunroll; /* Unroll counter for loop ops in side traces. */ int32_t loopunroll; /* Unroll counter for loop ops in side traces. */
uint64_t tailcalled; /* History of the number of successive tailcalls. */
int32_t framedepth; /* Current frame depth. */ int32_t framedepth; /* Current frame depth. */
int32_t retdepth; /* Return frame depth (count of RETF). */ int32_t retdepth; /* Return frame depth (count of RETF). */