Bug 604297 - TM: don't allow non-conditions to be passed to TraceRecorder::guard(). r=dmandelin.

This commit is contained in:
Nicholas Nethercote 2010-10-17 15:53:27 -07:00
parent 81e28f8cec
commit 3bd89f9f68
2 changed files with 36 additions and 10 deletions

View File

@ -4391,6 +4391,23 @@ TraceRecorder::createGuardRecord(VMSideExit* exit)
return gr;
}
/* Test if 'ins' is in a form that can be used as a guard/branch condition. */
static bool
isCond(LIns* ins)
{
return ins->isCmp() || ins->isImmI(0) || ins->isImmI(1);
}
/* Ensure 'ins' is in a form suitable for a guard/branch condition. */
void
TraceRecorder::ensureCond(LIns** ins, bool* cond)
{
if (!isCond(*ins)) {
*cond = !*cond;
*ins = (*ins)->isI() ? lir->insEqI_0(*ins) : lir->insEqP_0(*ins);
}
}
/*
* Emit a guard for condition (cond), expecting to evaluate to boolean result
* (expected) and using the supplied side exit if the condition doesn't hold.
@ -4423,10 +4440,7 @@ TraceRecorder::guard(bool expected, LIns* cond, VMSideExit* exit,
if (exit->exitType == LOOP_EXIT)
tree->sideExits.add(exit);
if (!cond->isCmp()) {
expected = !expected;
cond = cond->isI() ? lir->insEqI_0(cond) : lir->insEqP_0(cond);
}
JS_ASSERT(isCond(cond));
if ((cond->isImmI(0) && expected) || (cond->isImmI(1) && !expected)) {
if (abortIfAlwaysExits) {
@ -5534,6 +5548,12 @@ JS_REQUIRES_STACK void
TraceRecorder::emitIf(jsbytecode* pc, bool cond, LIns* x)
{
ExitType exitType;
/*
* Put 'x' in a form suitable for a guard/branch condition if it isn't
* already. This lets us detect if the comparison is optimized to 0 or 1,
* in which case we avoid the guard() call below.
*/
ensureCond(&x, &cond);
if (IsLoopEdge(pc, (jsbytecode*)tree->ip)) {
exitType = LOOP_EXIT;
@ -7302,7 +7322,11 @@ TraceRecorder::monitorRecording(JSOp op)
/* Handle one-shot request from finishGetProp or INSTANCEOF to snapshot post-op state and guard. */
if (pendingGuardCondition) {
guard(true, pendingGuardCondition, STATUS_EXIT);
LIns* cond = pendingGuardCondition;
bool expected = true;
/* Put 'cond' in a form suitable for a guard/branch condition if it's not already. */
ensureCond(&cond, &expected);
guard(expected, cond, STATUS_EXIT);
pendingGuardCondition = NULL;
}
@ -8410,9 +8434,9 @@ TraceRecorder::alu(LOpcode v, jsdouble v0, jsdouble v1, LIns* s0, LIns* s1)
LIns* br;
if (condBranch(LIR_jt, lir->ins2ImmI(LIR_gti, d1, 0), &br)) {
guard(false, lir->insEqI_0(d1), exit);
guard(false, lir->ins2(LIR_andi,
lir->ins2ImmI(LIR_eqi, d0, 0x80000000),
lir->ins2ImmI(LIR_eqi, d1, -1)), exit);
guard(true, lir->insEqI_0(lir->ins2(LIR_andi,
lir->ins2ImmI(LIR_eqi, d0, 0x80000000),
lir->ins2ImmI(LIR_eqi, d1, -1))), exit);
labelForBranch(br);
}
} else {
@ -16176,7 +16200,7 @@ TraceRecorder::record_JSOP_UNBRAND()
{
LIns* args_ins[] = { stack(-1), cx_ins };
LIns* call_ins = lir->insCall(&js_Unbrand_ci, args_ins);
guard(true, call_ins, OOM_EXIT);
guard(false, lir->insEqI_0(call_ins), OOM_EXIT);
return ARECORD_CONTINUE;
}
@ -16190,7 +16214,7 @@ TraceRecorder::record_JSOP_UNBRANDTHIS()
LIns* args_ins[] = { this_ins, cx_ins };
LIns* call_ins = lir->insCall(&js_Unbrand_ci, args_ins);
guard(true, call_ins, OOM_EXIT);
guard(false, lir->insEqI_0(call_ins), OOM_EXIT);
return ARECORD_CONTINUE;
}

View File

@ -1032,6 +1032,8 @@ class TraceRecorder
JS_REQUIRES_STACK bool lazilyImportGlobalSlot(unsigned slot);
JS_REQUIRES_STACK void importGlobalSlot(unsigned slot);
void ensureCond(nanojit::LIns** ins, bool* cond);
JS_REQUIRES_STACK RecordingStatus guard(bool expected, nanojit::LIns* cond, ExitType exitType,
bool abortIfAlwaysExits = false);
JS_REQUIRES_STACK RecordingStatus guard(bool expected, nanojit::LIns* cond, VMSideExit* exit,