mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-22 10:27:03 +00:00
Bug 600414 - TM: Use a more precise check for negative zero when multiplying (r=nnethercote)
This commit is contained in:
parent
07c37b877b
commit
8db35b0563
@ -1266,12 +1266,27 @@ Oracle::isInstructionUndemotable(jsbytecode* pc) const
|
|||||||
return _pcDontDemote.get(PCHash(pc));
|
return _pcDontDemote.get(PCHash(pc));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Tell the oracle that the instruction at bytecode location should use a stronger (slower) test for -0. */
|
||||||
|
void
|
||||||
|
Oracle::markInstructionSlowZeroTest(jsbytecode* pc)
|
||||||
|
{
|
||||||
|
_pcSlowZeroTest.set(PCHash(pc));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Consult with the oracle whether we should use a stronger (slower) test for -0. */
|
||||||
|
bool
|
||||||
|
Oracle::isInstructionSlowZeroTest(jsbytecode* pc) const
|
||||||
|
{
|
||||||
|
return _pcSlowZeroTest.get(PCHash(pc));
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Oracle::clearDemotability()
|
Oracle::clearDemotability()
|
||||||
{
|
{
|
||||||
_stackDontDemote.reset();
|
_stackDontDemote.reset();
|
||||||
_globalDontDemote.reset();
|
_globalDontDemote.reset();
|
||||||
_pcDontDemote.reset();
|
_pcDontDemote.reset();
|
||||||
|
_pcSlowZeroTest.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_REQUIRES_STACK void
|
JS_REQUIRES_STACK void
|
||||||
@ -6250,8 +6265,12 @@ TraceRecorder::attemptTreeCall(TreeFragment* f, uintN& inlineCallCount)
|
|||||||
: ARECORD_ABORTED;
|
: ARECORD_ABORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case MUL_ZERO_EXIT:
|
||||||
case OVERFLOW_EXIT:
|
case OVERFLOW_EXIT:
|
||||||
traceMonitor->oracle->markInstructionUndemotable(cx->regs->pc);
|
if (lr->exitType == MUL_ZERO_EXIT)
|
||||||
|
traceMonitor->oracle->markInstructionSlowZeroTest(cx->regs->pc);
|
||||||
|
else
|
||||||
|
traceMonitor->oracle->markInstructionUndemotable(cx->regs->pc);
|
||||||
/* FALL THROUGH */
|
/* FALL THROUGH */
|
||||||
case BRANCH_EXIT:
|
case BRANCH_EXIT:
|
||||||
case CASE_EXIT:
|
case CASE_EXIT:
|
||||||
@ -7221,8 +7240,12 @@ MonitorLoopEdge(JSContext* cx, uintN& inlineCallCount)
|
|||||||
#endif
|
#endif
|
||||||
return RecordingIfTrue(rv);
|
return RecordingIfTrue(rv);
|
||||||
|
|
||||||
|
case MUL_ZERO_EXIT:
|
||||||
case OVERFLOW_EXIT:
|
case OVERFLOW_EXIT:
|
||||||
tm->oracle->markInstructionUndemotable(cx->regs->pc);
|
if (lr->exitType == MUL_ZERO_EXIT)
|
||||||
|
tm->oracle->markInstructionSlowZeroTest(cx->regs->pc);
|
||||||
|
else
|
||||||
|
tm->oracle->markInstructionUndemotable(cx->regs->pc);
|
||||||
/* FALL THROUGH */
|
/* FALL THROUGH */
|
||||||
case BRANCH_EXIT:
|
case BRANCH_EXIT:
|
||||||
case CASE_EXIT:
|
case CASE_EXIT:
|
||||||
@ -8330,6 +8353,21 @@ TraceRecorder::stack(int n, LIns* i)
|
|||||||
set(&stackval(n), i);
|
set(&stackval(n), i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Leave trace iff one operand is negative and the other is non-negative. */
|
||||||
|
JS_REQUIRES_STACK void
|
||||||
|
TraceRecorder::guardNonNeg(LIns* d0, LIns* d1, VMSideExit* exit)
|
||||||
|
{
|
||||||
|
if (d0->isImmI())
|
||||||
|
JS_ASSERT(d0->immI() >= 0);
|
||||||
|
else
|
||||||
|
guard(false, lir->ins2ImmI(LIR_lti, d0, 0), exit);
|
||||||
|
|
||||||
|
if (d1->isImmI())
|
||||||
|
JS_ASSERT(d1->immI() >= 0);
|
||||||
|
else
|
||||||
|
guard(false, lir->ins2ImmI(LIR_lti, d1, 0), exit);
|
||||||
|
}
|
||||||
|
|
||||||
JS_REQUIRES_STACK LIns*
|
JS_REQUIRES_STACK LIns*
|
||||||
TraceRecorder::alu(LOpcode v, jsdouble v0, jsdouble v1, LIns* s0, LIns* s1)
|
TraceRecorder::alu(LOpcode v, jsdouble v0, jsdouble v1, LIns* s0, LIns* s1)
|
||||||
{
|
{
|
||||||
@ -8360,7 +8398,7 @@ TraceRecorder::alu(LOpcode v, jsdouble v0, jsdouble v1, LIns* s0, LIns* s1)
|
|||||||
break;
|
break;
|
||||||
case LIR_muld:
|
case LIR_muld:
|
||||||
r = v0 * v1;
|
r = v0 * v1;
|
||||||
if (r == 0.0)
|
if (r == 0.0 && (v0 < 0.0 || v1 < 0.0))
|
||||||
goto out;
|
goto out;
|
||||||
break;
|
break;
|
||||||
#if defined NANOJIT_IA32 || defined NANOJIT_X64
|
#if defined NANOJIT_IA32 || defined NANOJIT_X64
|
||||||
@ -8475,11 +8513,30 @@ TraceRecorder::alu(LOpcode v, jsdouble v0, jsdouble v1, LIns* s0, LIns* s1)
|
|||||||
result = lir->ins2(v, d0, d1);
|
result = lir->ins2(v, d0, d1);
|
||||||
}
|
}
|
||||||
if (needsNegZeroCheck) {
|
if (needsNegZeroCheck) {
|
||||||
// make sure we don't lose a -0
|
|
||||||
JS_ASSERT(v == LIR_muli);
|
JS_ASSERT(v == LIR_muli);
|
||||||
if (!exit)
|
|
||||||
exit = snapshot(OVERFLOW_EXIT);
|
/*
|
||||||
guard(false, lir->insEqI_0(result), exit);
|
* Make sure we don't lose a -0. We exit if the result is zero and if
|
||||||
|
* either operand is negative. We start out using a weaker guard, checking
|
||||||
|
* if either argument is negative. If this ever fails, we recompile with
|
||||||
|
* a stronger, but slower, guard.
|
||||||
|
*/
|
||||||
|
if (v0 < 0.0 || v1 < 0.0
|
||||||
|
|| !oracle || oracle->isInstructionSlowZeroTest(cx->regs->pc))
|
||||||
|
{
|
||||||
|
if (!exit)
|
||||||
|
exit = snapshot(OVERFLOW_EXIT);
|
||||||
|
|
||||||
|
guard(true,
|
||||||
|
lir->insEqI_0(lir->ins2(LIR_andi,
|
||||||
|
lir->insEqI_0(result),
|
||||||
|
lir->ins2(LIR_ori,
|
||||||
|
lir->ins2ImmI(LIR_lti, d0, 0),
|
||||||
|
lir->ins2ImmI(LIR_lti, d1, 0)))),
|
||||||
|
exit);
|
||||||
|
} else {
|
||||||
|
guardNonNeg(d0, d1, snapshot(MUL_ZERO_EXIT));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -16597,8 +16654,12 @@ MonitorTracePoint(JSContext* cx, uintN& inlineCallCount, bool& blacklist)
|
|||||||
return TPA_RanStuff;
|
return TPA_RanStuff;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case MUL_ZERO_EXIT:
|
||||||
case OVERFLOW_EXIT:
|
case OVERFLOW_EXIT:
|
||||||
tm->oracle->markInstructionUndemotable(cx->regs->pc);
|
if (lr->exitType == MUL_ZERO_EXIT)
|
||||||
|
tm->oracle->markInstructionSlowZeroTest(cx->regs->pc);
|
||||||
|
else
|
||||||
|
tm->oracle->markInstructionUndemotable(cx->regs->pc);
|
||||||
/* FALL THROUGH */
|
/* FALL THROUGH */
|
||||||
case BRANCH_EXIT:
|
case BRANCH_EXIT:
|
||||||
case CASE_EXIT:
|
case CASE_EXIT:
|
||||||
|
@ -303,6 +303,7 @@ class Oracle {
|
|||||||
avmplus::BitSet _stackDontDemote;
|
avmplus::BitSet _stackDontDemote;
|
||||||
avmplus::BitSet _globalDontDemote;
|
avmplus::BitSet _globalDontDemote;
|
||||||
avmplus::BitSet _pcDontDemote;
|
avmplus::BitSet _pcDontDemote;
|
||||||
|
avmplus::BitSet _pcSlowZeroTest;
|
||||||
public:
|
public:
|
||||||
Oracle();
|
Oracle();
|
||||||
|
|
||||||
@ -314,6 +315,8 @@ public:
|
|||||||
JS_REQUIRES_STACK bool isStackSlotUndemotable(JSContext* cx, unsigned slot, const void* pc) const;
|
JS_REQUIRES_STACK bool isStackSlotUndemotable(JSContext* cx, unsigned slot, const void* pc) const;
|
||||||
void markInstructionUndemotable(jsbytecode* pc);
|
void markInstructionUndemotable(jsbytecode* pc);
|
||||||
bool isInstructionUndemotable(jsbytecode* pc) const;
|
bool isInstructionUndemotable(jsbytecode* pc) const;
|
||||||
|
void markInstructionSlowZeroTest(jsbytecode* pc);
|
||||||
|
bool isInstructionSlowZeroTest(jsbytecode* pc) const;
|
||||||
|
|
||||||
void clearDemotability();
|
void clearDemotability();
|
||||||
void clear() {
|
void clear() {
|
||||||
@ -369,6 +372,7 @@ public:
|
|||||||
*/ \
|
*/ \
|
||||||
_(OOM) \
|
_(OOM) \
|
||||||
_(OVERFLOW) \
|
_(OVERFLOW) \
|
||||||
|
_(MUL_ZERO) \
|
||||||
_(UNSTABLE_LOOP) \
|
_(UNSTABLE_LOOP) \
|
||||||
_(TIMEOUT) \
|
_(TIMEOUT) \
|
||||||
_(DEEP_BAIL) \
|
_(DEEP_BAIL) \
|
||||||
@ -1111,6 +1115,7 @@ class TraceRecorder
|
|||||||
JS_REQUIRES_STACK nanojit::LIns* stack(int n);
|
JS_REQUIRES_STACK nanojit::LIns* stack(int n);
|
||||||
JS_REQUIRES_STACK void stack(int n, nanojit::LIns* i);
|
JS_REQUIRES_STACK void stack(int n, nanojit::LIns* i);
|
||||||
|
|
||||||
|
JS_REQUIRES_STACK void guardNonNeg(nanojit::LIns* d0, nanojit::LIns* d1, VMSideExit* exit);
|
||||||
JS_REQUIRES_STACK nanojit::LIns* alu(nanojit::LOpcode op, jsdouble v0, jsdouble v1,
|
JS_REQUIRES_STACK nanojit::LIns* alu(nanojit::LOpcode op, jsdouble v0, jsdouble v1,
|
||||||
nanojit::LIns* s0, nanojit::LIns* s1);
|
nanojit::LIns* s0, nanojit::LIns* s1);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user