Fixed JSOP_NEG with 0 being tracked as a promotable int, and added an equals-zero guard for the same opcode (bug 453049, r=gal).

This commit is contained in:
David Anderson 2008-09-03 23:27:58 -07:00
parent 1d44de3cb6
commit b791826dc5
2 changed files with 40 additions and 17 deletions

View File

@ -456,22 +456,6 @@ public:
{
}
LInsp ins1(LOpcode v, LInsp s0)
{
switch (v) {
case LIR_fneg:
if (isPromoteInt(s0)) {
LIns* result = out->ins1(LIR_neg, demote(out, s0));
out->insGuard(LIR_xt, out->ins1(LIR_ov, result),
recorder.snapshot(OVERFLOW_EXIT));
return out->ins1(LIR_i2f, result);
}
break;
default:;
}
return out->ins1(v, s0);
}
LInsp ins2(LOpcode v, LInsp s0, LInsp s1)
{
if (s0 == s1 && v == LIR_feq) {
@ -3897,7 +3881,29 @@ TraceRecorder::record_JSOP_BITNOT()
bool
TraceRecorder::record_JSOP_NEG()
{
return unary(LIR_fneg);
jsval& v = stackval(-1);
if (isNumber(v)) {
LIns* a = get(&v);
/* If we're a promoted integer, we have to watch out for 0s since -0 is a double.
Only follow this path if we're not an integer that's 0 and we're not a double
that's zero.
*/
if (isPromoteInt(a) &&
(!JSVAL_IS_INT(v) || JSVAL_TO_INT(v) != 0) &&
(!JSVAL_IS_DOUBLE(v) || !JSDOUBLE_IS_NEGZERO(*JSVAL_TO_DOUBLE(v)))) {
a = lir->ins1(LIR_neg, ::demote(lir, a));
lir->insGuard(LIR_xt, lir->ins1(LIR_ov, a), snapshot(OVERFLOW_EXIT));
lir->insGuard(LIR_xt, lir->ins2(LIR_eq, a, lir->insImm(0)), snapshot(OVERFLOW_EXIT));
a = lir->ins1(LIR_i2f, a);
} else {
a = lir->ins1(LIR_fneg, a);
}
set(&v, a);
return true;
}
return false;
}
enum JSTNErrType { INFALLIBLE, FAIL_NULL, FAIL_NEG, FAIL_VOID };

View File

@ -1167,6 +1167,23 @@ function testSwitchString() {
testSwitchString.expected = 200;
test(testSwitchString);
function testNegZero1Helper(z) {
for (let j = 0; j < 5; ++j) { z = -z; }
return Math.atan2(0, -0) == Math.atan2(0, z);
}
var testNegZero1 = function() { return testNegZero1Helper(0); }
testNegZero1.expected = true;
testNegZero1.name = 'testNegZero1';
testNegZero1Helper(1);
test(testNegZero1);
/* No test case, just make sure this doesn't assert. */
function testNegZero2() {
var z = 0;
for (let j = 0; j < 5; ++j) { ({p: (-z)}); }
}
testNegZero2();
/* Keep these at the end so that we can see the summary after the trace-debug spew. */
print("\npassed:", passes.length && passes.join(","));