Diff
Modified: trunk/LayoutTests/ChangeLog (149151 => 149152)
--- trunk/LayoutTests/ChangeLog 2013-04-25 22:51:08 UTC (rev 149151)
+++ trunk/LayoutTests/ChangeLog 2013-04-25 22:52:34 UTC (rev 149152)
@@ -1,3 +1,22 @@
+2013-04-25 Roman Zhuykov <[email protected]>
+
+ Arithmetic operations with negative zero should be optimized correclty.
+ https://bugs.webkit.org/show_bug.cgi?id=113862
+
+ Reviewed by Filip Pizlo.
+ * fast/js/regress/negative-zero-divide-expected.txt: Added.
+ * fast/js/regress/negative-zero-divide.html: Added.
+ * fast/js/regress/negative-zero-modulo-expected.txt: Added.
+ * fast/js/regress/negative-zero-modulo.html: Added.
+ * fast/js/regress/negative-zero-negate-expected.txt: Added.
+ * fast/js/regress/negative-zero-negate.html: Added.
+ * fast/js/regress/script-tests/negative-zero-divide.js: Added.
+ (foo):
+ * fast/js/regress/script-tests/negative-zero-modulo.js: Added.
+ (foo):
+ * fast/js/regress/script-tests/negative-zero-negate.js: Added.
+ (foo):
+
2013-04-25 Kent Tamura <[email protected]>
Ignore invalid regular expressions for input[pattern].
Added: trunk/LayoutTests/fast/js/regress/negative-zero-divide-expected.txt (0 => 149152)
--- trunk/LayoutTests/fast/js/regress/negative-zero-divide-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/js/regress/negative-zero-divide-expected.txt 2013-04-25 22:52:34 UTC (rev 149152)
@@ -0,0 +1,10 @@
+JSRegress/negative-zero-divide
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/fast/js/regress/negative-zero-divide.html (0 => 149152)
--- trunk/LayoutTests/fast/js/regress/negative-zero-divide.html (rev 0)
+++ trunk/LayoutTests/fast/js/regress/negative-zero-divide.html 2013-04-25 22:52:34 UTC (rev 149152)
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/fast/js/regress/negative-zero-modulo-expected.txt (0 => 149152)
--- trunk/LayoutTests/fast/js/regress/negative-zero-modulo-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/js/regress/negative-zero-modulo-expected.txt 2013-04-25 22:52:34 UTC (rev 149152)
@@ -0,0 +1,10 @@
+JSRegress/negative-zero-modulo
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/fast/js/regress/negative-zero-modulo.html (0 => 149152)
--- trunk/LayoutTests/fast/js/regress/negative-zero-modulo.html (rev 0)
+++ trunk/LayoutTests/fast/js/regress/negative-zero-modulo.html 2013-04-25 22:52:34 UTC (rev 149152)
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/fast/js/regress/negative-zero-negate-expected.txt (0 => 149152)
--- trunk/LayoutTests/fast/js/regress/negative-zero-negate-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/js/regress/negative-zero-negate-expected.txt 2013-04-25 22:52:34 UTC (rev 149152)
@@ -0,0 +1,10 @@
+JSRegress/negative-zero-negate
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/fast/js/regress/negative-zero-negate.html (0 => 149152)
--- trunk/LayoutTests/fast/js/regress/negative-zero-negate.html (rev 0)
+++ trunk/LayoutTests/fast/js/regress/negative-zero-negate.html 2013-04-25 22:52:34 UTC (rev 149152)
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/fast/js/regress/script-tests/negative-zero-divide.js (0 => 149152)
--- trunk/LayoutTests/fast/js/regress/script-tests/negative-zero-divide.js (rev 0)
+++ trunk/LayoutTests/fast/js/regress/script-tests/negative-zero-divide.js 2013-04-25 22:52:34 UTC (rev 149152)
@@ -0,0 +1,19 @@
+function foo() {
+ var x = 1;
+ var y = -1;
+ var s;
+ var i;
+ for (i = 0; i < 2001; i++) {
+ if (i == 2000)
+ x = 0;
+ s = 1/(x/y+(-0));
+ }
+ return s;
+}
+
+var x = (1/(0/-1+(-0))).toString();
+var y = foo().toString();
+
+if (x != y)
+ throw "Error: bad result: " + y;
+
Added: trunk/LayoutTests/fast/js/regress/script-tests/negative-zero-modulo.js (0 => 149152)
--- trunk/LayoutTests/fast/js/regress/script-tests/negative-zero-modulo.js (rev 0)
+++ trunk/LayoutTests/fast/js/regress/script-tests/negative-zero-modulo.js 2013-04-25 22:52:34 UTC (rev 149152)
@@ -0,0 +1,18 @@
+function foo() {
+ var x = 4;
+ var s;
+ var i;
+ for (i = 0; i < 2001; i++) {
+ if (i == 2000)
+ x = -4;
+ s = 1/(x%4);
+ }
+ return s;
+}
+
+var x = (1/((-4)%4)).toString();
+var y = foo().toString();
+
+if (x != y)
+ throw "Error: bad result: " + y;
+
Added: trunk/LayoutTests/fast/js/regress/script-tests/negative-zero-negate.js (0 => 149152)
--- trunk/LayoutTests/fast/js/regress/script-tests/negative-zero-negate.js (rev 0)
+++ trunk/LayoutTests/fast/js/regress/script-tests/negative-zero-negate.js 2013-04-25 22:52:34 UTC (rev 149152)
@@ -0,0 +1,18 @@
+function foo() {
+ var x = 1;
+ var s;
+ var i;
+ for (i = 0; i < 2001; i++) {
+ if (i == 2000)
+ x = 0;
+ s = 1/(-x);
+ }
+ return s;
+}
+
+var x = (1/(-0)).toString();
+var y = foo().toString();
+
+if (x != y)
+ throw "Error: bad result: " + y;
+
Modified: trunk/Source/_javascript_Core/ChangeLog (149151 => 149152)
--- trunk/Source/_javascript_Core/ChangeLog 2013-04-25 22:51:08 UTC (rev 149151)
+++ trunk/Source/_javascript_Core/ChangeLog 2013-04-25 22:52:34 UTC (rev 149152)
@@ -1,3 +1,44 @@
+2013-04-25 Roman Zhuykov <[email protected]>
+
+ Fix problems with processing negative zero on DFG.
+ https://bugs.webkit.org/show_bug.cgi?id=113862
+
+ Reviewed by Filip Pizlo.
+
+ Fix NodeNeedsNegZero flag propagation in BackwardPropagationPhase.
+ Function arithNodeFlags should not mask NodeNeedsNegZero flag for ArithNegate and DoubleAsInt32
+ nodes and this flag should be always used to decide where we need to generate nezative-zero checks.
+ Remove unnecessary negative-zero checks from integer ArithDiv on ARM.
+ Also remove such checks from integer ArithMod on ARM and X86, and make them always to
+ check not only "modulo_result == 0" but also "dividend < 0".
+ Generate faster code for case when ArithMod operation divisor is constant power of 2 on ARMv7
+ in the same way as on ARMv7s, and add negative-zero checks into this code when needed.
+ Change speculationCheck ExitKind from Overflow to NegativeZero where applicable.
+
+ This shows 30% speedup of math-spectral-norm, and 5% speedup
+ on SunSpider overall on ARMv7 Linux.
+
+ * assembler/MacroAssemblerARM.h:
+ (JSC::MacroAssemblerARM::branchConvertDoubleToInt32):
+ * assembler/MacroAssemblerARMv7.h:
+ (JSC::MacroAssemblerARMv7::branchConvertDoubleToInt32):
+ * assembler/MacroAssemblerMIPS.h:
+ (JSC::MacroAssemblerMIPS::branchConvertDoubleToInt32):
+ * assembler/MacroAssemblerSH4.h:
+ (JSC::MacroAssemblerSH4::branchConvertDoubleToInt32):
+ * assembler/MacroAssemblerX86Common.h:
+ (JSC::MacroAssemblerX86Common::branchConvertDoubleToInt32):
+ * dfg/DFGBackwardsPropagationPhase.cpp:
+ (JSC::DFG::BackwardsPropagationPhase::isNotNegZero):
+ (JSC::DFG::BackwardsPropagationPhase::isNotPosZero):
+ (JSC::DFG::BackwardsPropagationPhase::propagate):
+ * dfg/DFGNode.h:
+ (JSC::DFG::Node::arithNodeFlags):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compileDoubleAsInt32):
+ (JSC::DFG::SpeculativeJIT::compileSoftModulo):
+ (JSC::DFG::SpeculativeJIT::compileArithNegate):
+
2013-04-25 Oliver Hunt <[email protected]>
Stack guards are too conservative
Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerARM.h (149151 => 149152)
--- trunk/Source/_javascript_Core/assembler/MacroAssemblerARM.h 2013-04-25 22:51:08 UTC (rev 149151)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerARM.h 2013-04-25 22:52:34 UTC (rev 149152)
@@ -1244,7 +1244,7 @@
// If the result is not representable as a 32 bit value, branch.
// May also branch for some values that are representable in 32 bits
// (specifically, in this case, 0).
- void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID)
+ void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID, bool negZeroCheck = true)
{
m_assembler.vcvt_s32_f64(ARMRegisters::SD0 << 1, src);
m_assembler.vmov_arm32(dest, ARMRegisters::SD0 << 1);
@@ -1254,7 +1254,8 @@
failureCases.append(branchDouble(DoubleNotEqualOrUnordered, src, ARMRegisters::SD0));
// If the result is zero, it might have been -0.0, and 0.0 equals to -0.0
- failureCases.append(branchTest32(Zero, dest));
+ if (negZeroCheck)
+ failureCases.append(branchTest32(Zero, dest));
}
Jump branchDoubleNonZero(FPRegisterID reg, FPRegisterID scratch)
Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerARMv7.h (149151 => 149152)
--- trunk/Source/_javascript_Core/assembler/MacroAssemblerARMv7.h 2013-04-25 22:51:08 UTC (rev 149151)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerARMv7.h 2013-04-25 22:52:34 UTC (rev 149152)
@@ -1104,7 +1104,7 @@
// If the result is not representable as a 32 bit value, branch.
// May also branch for some values that are representable in 32 bits
// (specifically, in this case, 0).
- void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID)
+ void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID, bool negZeroCheck = true)
{
m_assembler.vcvt_floatingPointToSigned(fpTempRegisterAsSingle(), src);
m_assembler.vmov(dest, fpTempRegisterAsSingle());
@@ -1114,7 +1114,8 @@
failureCases.append(branchDouble(DoubleNotEqualOrUnordered, src, fpTempRegister));
// If the result is zero, it might have been -0.0, and the double comparison won't catch this!
- failureCases.append(branchTest32(Zero, dest));
+ if (negZeroCheck)
+ failureCases.append(branchTest32(Zero, dest));
}
Jump branchDoubleNonZero(FPRegisterID reg, FPRegisterID)
Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerMIPS.h (149151 => 149152)
--- trunk/Source/_javascript_Core/assembler/MacroAssemblerMIPS.h 2013-04-25 22:51:08 UTC (rev 149151)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerMIPS.h 2013-04-25 22:52:34 UTC (rev 149152)
@@ -2629,13 +2629,14 @@
// If the result is not representable as a 32 bit value, branch.
// May also branch for some values that are representable in 32 bits
// (specifically, in this case, 0).
- void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp)
+ void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp, bool negZeroCheck = true)
{
m_assembler.cvtwd(fpTempRegister, src);
m_assembler.mfc1(dest, fpTempRegister);
// If the result is zero, it might have been -0.0, and the double comparison won't catch this!
- failureCases.append(branch32(Equal, dest, MIPSRegisters::zero));
+ if (negZeroCheck)
+ failureCases.append(branch32(Equal, dest, MIPSRegisters::zero));
// Convert the integer result back to float & compare to the original value - if not equal or unordered (NaN) then jump.
convertInt32ToDouble(dest, fpTemp);
Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerSH4.h (149151 => 149152)
--- trunk/Source/_javascript_Core/assembler/MacroAssemblerSH4.h 2013-04-25 22:51:08 UTC (rev 149151)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerSH4.h 2013-04-25 22:52:34 UTC (rev 149152)
@@ -2036,20 +2036,22 @@
return branchTrue();
}
- void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp)
+ void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp, bool negZeroCheck = true)
{
m_assembler.ftrcdrmfpul(src);
m_assembler.stsfpulReg(dest);
convertInt32ToDouble(dest, fscratch);
failureCases.append(branchDouble(DoubleNotEqualOrUnordered, fscratch, src));
- if (dest == SH4Registers::r0)
- m_assembler.cmpEqImmR0(0, dest);
- else {
- m_assembler.movImm8(0, scratchReg3);
- m_assembler.cmplRegReg(scratchReg3, dest, SH4Condition(Equal));
+ if (negZeroCheck) {
+ if (dest == SH4Registers::r0)
+ m_assembler.cmpEqImmR0(0, dest);
+ else {
+ m_assembler.movImm8(0, scratchReg3);
+ m_assembler.cmplRegReg(scratchReg3, dest, SH4Condition(Equal));
+ }
+ failureCases.append(branchTrue());
}
- failureCases.append(branchTrue());
}
void neg32(RegisterID dst)
Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h (149151 => 149152)
--- trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h 2013-04-25 22:51:08 UTC (rev 149151)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h 2013-04-25 22:52:34 UTC (rev 149152)
@@ -885,13 +885,14 @@
// If the result is not representable as a 32 bit value, branch.
// May also branch for some values that are representable in 32 bits
// (specifically, in this case, 0).
- void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp)
+ void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp, bool negZeroCheck = true)
{
ASSERT(isSSE2Present());
m_assembler.cvttsd2si_rr(src, dest);
// If the result is zero, it might have been -0.0, and the double comparison won't catch this!
- failureCases.append(branchTest32(Zero, dest));
+ if (negZeroCheck)
+ failureCases.append(branchTest32(Zero, dest));
// Convert the integer result back to float & compare to the original value - if not equal or unordered (NaN) then jump.
convertInt32ToDouble(dest, fpTemp);
Modified: trunk/Source/_javascript_Core/dfg/DFGBackwardsPropagationPhase.cpp (149151 => 149152)
--- trunk/Source/_javascript_Core/dfg/DFGBackwardsPropagationPhase.cpp 2013-04-25 22:51:08 UTC (rev 149151)
+++ trunk/Source/_javascript_Core/dfg/DFGBackwardsPropagationPhase.cpp 2013-04-25 22:52:34 UTC (rev 149152)
@@ -66,14 +66,15 @@
if (!m_graph.isNumberConstant(node))
return false;
double value = m_graph.valueOfNumberConstant(node);
- return !value && 1.0 / value < 0.0;
+ return (value || 1.0 / value > 0.0);
}
- bool isNotZero(Node* node)
+ bool isNotPosZero(Node* node)
{
if (!m_graph.isNumberConstant(node))
return false;
- return !!m_graph.valueOfNumberConstant(node);
+ double value = m_graph.valueOfNumberConstant(node);
+ return (value || 1.0 / value < 0.0);
}
// Tests if the absolute value is strictly less than the power of two.
@@ -247,7 +248,7 @@
}
case ArithSub: {
- if (isNotZero(node->child1().node()) || isNotZero(node->child2().node()))
+ if (isNotNegZero(node->child1().node()) || isNotPosZero(node->child2().node()))
flags &= ~NodeNeedsNegZero;
if (!isWithinPowerOfTwo<32>(node->child1()) && !isWithinPowerOfTwo<32>(node->child2()))
flags |= NodeUsedAsNumber;
Modified: trunk/Source/_javascript_Core/dfg/DFGNode.h (149151 => 149152)
--- trunk/Source/_javascript_Core/dfg/DFGNode.h 2013-04-25 22:51:08 UTC (rev 149151)
+++ trunk/Source/_javascript_Core/dfg/DFGNode.h 2013-04-25 22:52:34 UTC (rev 149152)
@@ -522,7 +522,7 @@
NodeFlags arithNodeFlags()
{
NodeFlags result = m_flags & NodeArithFlagsMask;
- if (op() == ArithMul || op() == ArithDiv || op() == ArithMod)
+ if (op() == ArithMul || op() == ArithDiv || op() == ArithMod || op() == ArithNegate || op() == DoubleAsInt32)
return result;
return result & ~NodeNeedsNegZero;
}
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (149151 => 149152)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2013-04-25 22:51:08 UTC (rev 149151)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2013-04-25 22:52:34 UTC (rev 149152)
@@ -2395,7 +2395,8 @@
GPRReg resultGPR = result.gpr();
JITCompiler::JumpList failureCases;
- m_jit.branchConvertDoubleToInt32(valueFPR, resultGPR, failureCases, scratchFPR);
+ bool negZeroCheck = !nodeCanIgnoreNegativeZero(node->arithNodeFlags());
+ m_jit.branchConvertDoubleToInt32(valueFPR, resultGPR, failureCases, scratchFPR, negZeroCheck);
forwardSpeculationCheck(Overflow, JSValueRegs(), 0, failureCases, ValueRecovery::inFPR(valueFPR));
integerResult(resultGPR, node);
@@ -2908,12 +2909,12 @@
speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branch32(JITCompiler::Equal, eax.gpr(), TrustedImm32(-2147483647-1)));
m_jit.assembler().cdq();
m_jit.assembler().idivl_r(scratchGPR);
- // Check that we're not about to create negative zero.
- // FIXME: if the node use doesn't care about neg zero, we can do this more easily.
- JITCompiler::Jump numeratorPositive = m_jit.branch32(JITCompiler::GreaterThanOrEqual, op1SaveGPR, TrustedImm32(0));
- speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchTest32(JITCompiler::Zero, edx.gpr()));
- numeratorPositive.link(&m_jit);
-
+ if (!nodeCanIgnoreNegativeZero(node->arithNodeFlags())) {
+ // Check that we're not about to create negative zero.
+ JITCompiler::Jump numeratorPositive = m_jit.branch32(JITCompiler::GreaterThanOrEqual, op1SaveGPR, TrustedImm32(0));
+ speculationCheck(NegativeZero, JSValueRegs(), 0, m_jit.branchTest32(JITCompiler::Zero, edx.gpr()));
+ numeratorPositive.link(&m_jit);
+ }
if (op1SaveGPR != op1Gpr)
unlock(op1SaveGPR);
@@ -2921,7 +2922,7 @@
return;
}
}
-#elif CPU(APPLE_ARMV7S)
+#elif CPU(APPLE_ARMV7S) || CPU(ARM_THUMB2)
if (isInt32Constant(node->child2().node())) {
int32_t divisor = valueOfInt32Constant(node->child2().node());
if (divisor > 0 && hasOneBitSet(divisor)) { // If power of 2 then just mask
@@ -2937,6 +2938,12 @@
m_jit.assembler().it(ARMv7Assembler::ConditionLT);
m_jit.assembler().neg(resultGPR, resultGPR);
+ if (!nodeCanIgnoreNegativeZero(node->arithNodeFlags())) {
+ // Check that we're not about to create negative zero.
+ JITCompiler::Jump numeratorPositive = m_jit.branch32(JITCompiler::GreaterThanOrEqual, dividendGPR, TrustedImm32(0));
+ speculationCheck(NegativeZero, JSValueRegs(), 0, m_jit.branchTest32(JITCompiler::Zero, resultGPR));
+ numeratorPositive.link(&m_jit);
+ }
integerResult(resultGPR, node);
return;
}
@@ -3000,11 +3007,12 @@
if (op2TempGPR != InvalidGPRReg)
unlock(op2TempGPR);
- // Check that we're not about to create negative zero.
- // FIXME: if the node use doesn't care about neg zero, we can do this more easily.
- JITCompiler::Jump numeratorPositive = m_jit.branch32(JITCompiler::GreaterThanOrEqual, op1SaveGPR, TrustedImm32(0));
- speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchTest32(JITCompiler::Zero, edx.gpr()));
- numeratorPositive.link(&m_jit);
+ if (!nodeCanIgnoreNegativeZero(node->arithNodeFlags())) {
+ // Check that we're not about to create negative zero.
+ JITCompiler::Jump numeratorPositive = m_jit.branch32(JITCompiler::GreaterThanOrEqual, op1SaveGPR, TrustedImm32(0));
+ speculationCheck(NegativeZero, JSValueRegs(), 0, m_jit.branchTest32(JITCompiler::Zero, edx.gpr()));
+ numeratorPositive.link(&m_jit);
+ }
if (op1SaveGPR != op1GPR)
unlock(op1SaveGPR);
@@ -3029,7 +3037,7 @@
if (!nodeCanIgnoreNegativeZero(node->arithNodeFlags())) {
// Check that we're not about to create negative zero.
JITCompiler::Jump numeratorPositive = m_jit.branch32(JITCompiler::GreaterThanOrEqual, dividendGPR, TrustedImm32(0));
- speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchTest32(JITCompiler::Zero, quotientThenRemainderGPR));
+ speculationCheck(NegativeZero, JSValueRegs(), 0, m_jit.branchTest32(JITCompiler::Zero, quotientThenRemainderGPR));
numeratorPositive.link(&m_jit);
}
@@ -3048,8 +3056,14 @@
FPRTemporary scratch(this);
GPRTemporary intResult(this);
JITCompiler::JumpList failureCases;
- m_jit.branchConvertDoubleToInt32(result.fpr(), intResult.gpr(), failureCases, scratch.fpr());
+ m_jit.branchConvertDoubleToInt32(result.fpr(), intResult.gpr(), failureCases, scratch.fpr(), false);
speculationCheck(Overflow, JSValueRegs(), 0, failureCases);
+ if (!nodeCanIgnoreNegativeZero(node->arithNodeFlags())) {
+ // Check that we're not about to create negative zero.
+ JITCompiler::Jump numeratorPositive = m_jit.branch32(JITCompiler::GreaterThanOrEqual, op1GPR, TrustedImm32(0));
+ speculationCheck(NegativeZero, JSValueRegs(), 0, m_jit.branchTest32(JITCompiler::Zero, intResult.gpr()));
+ numeratorPositive.link(&m_jit);
+ }
integerResult(intResult.gpr(), node);
#endif // CPU(X86) || CPU(X86_64)
@@ -3296,7 +3310,7 @@
else {
speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchNeg32(MacroAssembler::Overflow, result.gpr()));
if (!nodeCanIgnoreNegativeZero(node->arithNodeFlags()))
- speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchTest32(MacroAssembler::Zero, result.gpr()));
+ speculationCheck(NegativeZero, JSValueRegs(), 0, m_jit.branchTest32(MacroAssembler::Zero, result.gpr()));
}
integerResult(result.gpr(), node);