Implement down-recursion.

This commit is contained in:
Mike Pall
2010-03-01 06:45:30 +01:00
parent 69ea553024
commit e7b737aa12
7 changed files with 114 additions and 13 deletions

View File

@@ -357,6 +357,8 @@ static void trace_start(jit_State *J)
if ((J->pt->flags & PROTO_NO_JIT)) { /* JIT disabled for this proto? */
if (J->parent == 0) {
/* Lazy bytecode patching to disable hotcount events. */
lua_assert(bc_op(*J->pc) == BC_FORL || bc_op(*J->pc) == BC_ITERL ||
bc_op(*J->pc) == BC_LOOP || bc_op(*J->pc) == BC_FUNCF);
setbc_op(J->pc, (int)bc_op(*J->pc)+(int)BC_ILOOP-(int)BC_LOOP);
J->pt->flags |= PROTO_HAS_ILOOP;
}
@@ -416,10 +418,16 @@ static void trace_stop(jit_State *J)
/* Patch bytecode of starting instruction in root trace. */
setbc_op(pc, (int)op+(int)BC_JLOOP-(int)BC_LOOP);
setbc_d(pc, J->curtrace);
addroot:
/* Add to root trace chain in prototype. */
J->cur.nextroot = pt->trace;
pt->trace = (TraceNo1)J->curtrace;
break;
case BC_RET:
case BC_RET0:
case BC_RET1:
*pc = BCINS_AD(BC_JLOOP, J->cur.snap[0].nslots, J->curtrace);
goto addroot;
case BC_JMP:
/* Patch exit branch in parent to side trace entry. */
lua_assert(J->parent != 0 && J->cur.root != 0);
@@ -450,6 +458,21 @@ static void trace_stop(jit_State *J)
);
}
/* Start a new root trace for down-recursion. */
static int trace_downrec(jit_State *J)
{
/* Restart recording at the return instruction. */
lua_assert(J->pt != NULL);
lua_assert(bc_isret(bc_op(*J->pc)));
if (bc_op(*J->pc) == BC_RETM)
return 0; /* NYI: down-recursion with RETM. */
J->parent = 0;
J->exitno = 0;
J->state = LJ_TRACE_RECORD;
trace_start(J);
return 1;
}
/* Abort tracing. */
static int trace_abort(jit_State *J)
{
@@ -463,7 +486,7 @@ static int trace_abort(jit_State *J)
return 1; /* Retry ASM with new MCode area. */
}
/* Penalize or blacklist starting bytecode instruction. */
if (J->parent == 0)
if (J->parent == 0 && !bc_isret(bc_op(J->cur.startins)))
penalty_pc(J, &gcref(J->cur.startpt)->pt, (BCIns *)J->startpc, e);
if (J->curtrace) { /* Is there anything to abort? */
ptrdiff_t errobj = savestack(L, L->top-1); /* Stack may be resized. */
@@ -493,17 +516,29 @@ static int trace_abort(jit_State *J)
J->curtrace = 0;
}
L->top--; /* Remove error object */
if (e == LJ_TRERR_MCODEAL)
if (e == LJ_TRERR_DOWNREC)
return trace_downrec(J);
else if (e == LJ_TRERR_MCODEAL)
lj_trace_flushall(L);
return 0;
}
/* Perform pending re-patch of a bytecode instruction. */
static LJ_AINLINE void trace_pendpatch(jit_State *J, int force)
{
if (LJ_UNLIKELY(J->patchpc) && (force || J->chain[IR_RETF])) {
*J->patchpc = J->patchins;
J->patchpc = NULL;
}
}
/* State machine for the trace compiler. Protected callback. */
static TValue *trace_state(lua_State *L, lua_CFunction dummy, void *ud)
{
jit_State *J = (jit_State *)ud;
UNUSED(dummy);
do {
retry:
switch (J->state) {
case LJ_TRACE_START:
J->state = LJ_TRACE_RECORD; /* trace_start() may change state. */
@@ -512,6 +547,7 @@ static TValue *trace_state(lua_State *L, lua_CFunction dummy, void *ud)
break;
case LJ_TRACE_RECORD:
trace_pendpatch(J, 0);
setvmstate(J2G(J), RECORD);
lj_vmevent_send(L, RECORD,
setintV(L->top++, J->curtrace);
@@ -523,6 +559,7 @@ static TValue *trace_state(lua_State *L, lua_CFunction dummy, void *ud)
break;
case LJ_TRACE_END:
trace_pendpatch(J, 1);
J->loopref = 0;
if ((J->flags & JIT_F_OPT_LOOP) &&
J->cur.link == J->curtrace && J->framedepth + J->retdepth == 0) {
@@ -551,8 +588,9 @@ static TValue *trace_state(lua_State *L, lua_CFunction dummy, void *ud)
setintV(L->top++, (int32_t)LJ_TRERR_RECERR);
/* fallthrough */
case LJ_TRACE_ERR:
trace_pendpatch(J, 1);
if (trace_abort(J))
break; /* Retry. */
goto retry;
setvmstate(J2G(J), INTERP);
J->state = LJ_TRACE_IDLE;
lj_dispatch_update(J2G(J));
@@ -627,6 +665,7 @@ int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr)
lua_State *L = J->L;
ExitDataCP exd;
int errcode;
const BCIns *pc;
exd.J = J;
exd.exptr = exptr;
errcode = lj_vm_cpcall(L, NULL, &exd, trace_exit_cp);
@@ -651,8 +690,21 @@ int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr)
}
);
trace_hotside(J, exd.pc);
setcframe_pc(cframe_raw(L->cframe), exd.pc);
pc = exd.pc;
trace_hotside(J, pc);
if (bc_op(*pc) == BC_JLOOP) {
BCIns *retpc = &J->trace[bc_d(*pc)]->startins;
if (bc_isret(bc_op(*retpc))) {
if (J->state == LJ_TRACE_RECORD) {
J->patchins = *pc;
J->patchpc = (BCIns *)pc;
*J->patchpc = *retpc;
} else {
pc = retpc;
}
}
}
setcframe_pc(cframe_raw(L->cframe), pc);
return 0;
}