Ensure forward progress on trace exit to BC_ITERN.
Also use a safer way to force a static dispatch for BC_RET*. Reported by Bartel Eerdekens. Analyzed by Peter Cawley. #1000 #1045
This commit is contained in:
@@ -431,6 +431,12 @@ static void trace_start(jit_State *J)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Ensuring forward progress for BC_ITERN can trigger hotcount again. */
|
||||
if (!J->parent && bc_op(*J->pc) == BC_JLOOP) { /* Already compiled. */
|
||||
J->state = LJ_TRACE_IDLE; /* Silently ignored. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get a new trace number. */
|
||||
traceno = trace_findfree(J);
|
||||
if (LJ_UNLIKELY(traceno == 0)) { /* No free trace? */
|
||||
@@ -867,7 +873,7 @@ int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr)
|
||||
ExitDataCP exd;
|
||||
int errcode, exitcode = J->exitcode;
|
||||
TValue exiterr;
|
||||
const BCIns *pc;
|
||||
const BCIns *pc, *retpc;
|
||||
void *cf;
|
||||
GCtrace *T;
|
||||
|
||||
@@ -919,22 +925,7 @@ int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr)
|
||||
} else {
|
||||
trace_hotside(J, pc);
|
||||
}
|
||||
if (bc_op(*pc) == BC_JLOOP) {
|
||||
BCIns *retpc = &traceref(J, bc_d(*pc))->startins;
|
||||
int isret = bc_isret(bc_op(*retpc));
|
||||
if (isret || bc_op(*retpc) == BC_ITERN) {
|
||||
if (J->state == LJ_TRACE_RECORD) {
|
||||
J->patchins = *pc;
|
||||
J->patchpc = (BCIns *)pc;
|
||||
*J->patchpc = *retpc;
|
||||
J->bcskip = 1;
|
||||
} else if (isret) {
|
||||
pc = retpc;
|
||||
setcframe_pc(cf, pc);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Return MULTRES or 0. */
|
||||
/* Return MULTRES or 0 or -17. */
|
||||
ERRNO_RESTORE
|
||||
switch (bc_op(*pc)) {
|
||||
case BC_CALLM: case BC_CALLMT:
|
||||
@@ -943,6 +934,18 @@ int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr)
|
||||
return (int)((BCReg)(L->top - L->base) + 1 - bc_a(*pc) - bc_d(*pc));
|
||||
case BC_TSETM:
|
||||
return (int)((BCReg)(L->top - L->base) + 1 - bc_a(*pc));
|
||||
case BC_JLOOP:
|
||||
retpc = &traceref(J, bc_d(*pc))->startins;
|
||||
if (bc_isret(bc_op(*retpc)) || bc_op(*retpc) == BC_ITERN) {
|
||||
/* Dispatch to original ins to ensure forward progress. */
|
||||
if (J->state != LJ_TRACE_RECORD) return -17;
|
||||
/* Unpatch bytecode when recording. */
|
||||
J->patchins = *pc;
|
||||
J->patchpc = (BCIns *)pc;
|
||||
*J->patchpc = *retpc;
|
||||
J->bcskip = 1;
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
if (bc_op(*pc) >= BC_FUNCF)
|
||||
return (int)((BCReg)(L->top - L->base) + 1);
|
||||
|
||||
Reference in New Issue
Block a user