mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
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:
parent
1d44de3cb6
commit
b791826dc5
@ -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 };
|
||||
|
@ -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(","));
|
||||
|
Loading…
Reference in New Issue
Block a user