Make the different flavors of integer arithmetic more explicit, and don't rely on (possibly stale) results of the backwards propagator to decide integer arithmetic semantics
https://bugs.webkit.org/show_bug.cgi?id=125519
Reviewed by Geoffrey Garen.
Adds the Arith::Mode enum to arithmetic nodes, which makes it explicit what sorts of
checks and overflows the node should do. Previously this would be deduced from
backwards analysis results.
This also makes "unchecked" variants really mean that you want the int32 wrapped
result, so ArithIMul is now done in terms of ArithMul(Unchecked). That means that the
constant folder needs to compute exactly the result implied by ArithMode, instead of
just folding the double result.
* CMakeLists.txt:
* GNUmakefile.list.am:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGArithMode.cpp: Added.
(WTF::printInternal):
* dfg/DFGArithMode.h: Added.
(JSC::DFG::doesOverflow):
(JSC::DFG::shouldCheckOverflow):
(JSC::DFG::shouldCheckNegativeZero):
* dfg/DFGCSEPhase.cpp:
(JSC::DFG::CSEPhase::pureCSE):
(JSC::DFG::CSEPhase::performNodeCSE):
* dfg/DFGConstantFoldingPhase.cpp:
(JSC::DFG::ConstantFoldingPhase::foldConstants):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
(JSC::DFG::FixupPhase::attemptToMakeIntegerAdd):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::dump):
* dfg/DFGNode.h:
(JSC::DFG::Node::Node):
(JSC::DFG::Node::hasArithMode):
(JSC::DFG::Node::arithMode):
(JSC::DFG::Node::setArithMode):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileUInt32ToNumber):
(JSC::DFG::SpeculativeJIT::compileDoubleAsInt32):
(JSC::DFG::SpeculativeJIT::compileAdd):
(JSC::DFG::SpeculativeJIT::compileArithSub):
(JSC::DFG::SpeculativeJIT::compileArithNegate):
(JSC::DFG::SpeculativeJIT::compileArithMul):
(JSC::DFG::SpeculativeJIT::compileArithDiv):
(JSC::DFG::SpeculativeJIT::compileArithMod):
* dfg/DFGSpeculativeJIT.h:
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::compileAddSub):
(JSC::FTL::LowerDFGToLLVM::compileArithMul):
(JSC::FTL::LowerDFGToLLVM::compileArithDivMod):
(JSC::FTL::LowerDFGToLLVM::compileArithNegate):
(JSC::FTL::LowerDFGToLLVM::compileUInt32ToNumber):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@161399 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
index 25eb9b5..08e353e 100644
--- a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
@@ -103,10 +103,19 @@
case BitXor:
case BitRShift:
case BitLShift:
- case BitURShift:
+ case BitURShift: {
+ fixIntEdge(node->child1());
+ fixIntEdge(node->child2());
+ break;
+ }
+
case ArithIMul: {
fixIntEdge(node->child1());
fixIntEdge(node->child2());
+ node->setOp(ArithMul);
+ node->setArithMode(Arith::Unchecked);
+ node->child1().setUseKind(Int32Use);
+ node->child2().setUseKind(Int32Use);
break;
}
@@ -114,6 +123,10 @@
fixEdge<KnownInt32Use>(node->child1());
if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
node->convertToIdentity();
+ else if (nodeCanSpeculateInt32(node->arithNodeFlags()))
+ node->setArithMode(Arith::CheckOverflow);
+ else
+ node->setArithMode(Arith::DoOverflow);
break;
}
@@ -210,10 +223,20 @@
case ArithNegate: {
if (m_graph.negateShouldSpeculateInt32(node)) {
fixEdge<Int32Use>(node->child1());
+ if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
+ node->setArithMode(Arith::Unchecked);
+ else if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
+ node->setArithMode(Arith::CheckOverflow);
+ else
+ node->setArithMode(Arith::CheckOverflowAndNegativeZero);
break;
}
if (m_graph.negateShouldSpeculateMachineInt(node)) {
fixEdge<MachineIntUse>(node->child1());
+ if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
+ node->setArithMode(Arith::CheckOverflow);
+ else
+ node->setArithMode(Arith::CheckOverflowAndNegativeZero);
break;
}
fixEdge<NumberUse>(node->child1());
@@ -224,11 +247,21 @@
if (m_graph.mulShouldSpeculateInt32(node)) {
fixEdge<Int32Use>(node->child1());
fixEdge<Int32Use>(node->child2());
+ if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
+ node->setArithMode(Arith::Unchecked);
+ else if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
+ node->setArithMode(Arith::CheckOverflow);
+ else
+ node->setArithMode(Arith::CheckOverflowAndNegativeZero);
break;
}
if (m_graph.mulShouldSpeculateMachineInt(node)) {
fixEdge<MachineIntUse>(node->child1());
fixEdge<MachineIntUse>(node->child2());
+ if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
+ node->setArithMode(Arith::CheckOverflow);
+ else
+ node->setArithMode(Arith::CheckOverflowAndNegativeZero);
break;
}
fixEdge<NumberUse>(node->child1());
@@ -243,6 +276,12 @@
if (optimizeForX86() || optimizeForARM64() || optimizeForARMv7s()) {
fixEdge<Int32Use>(node->child1());
fixEdge<Int32Use>(node->child2());
+ if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
+ node->setArithMode(Arith::Unchecked);
+ else if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
+ node->setArithMode(Arith::CheckOverflow);
+ else
+ node->setArithMode(Arith::CheckOverflowAndNegativeZero);
break;
}
Edge child1 = node->child1();
@@ -258,6 +297,10 @@
node->setOp(DoubleAsInt32);
node->children.initialize(Edge(newDivision, KnownNumberUse), Edge(), Edge());
+ if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
+ node->setArithMode(Arith::CheckOverflow);
+ else
+ node->setArithMode(Arith::CheckOverflowAndNegativeZero);
m_insertionSet.insertNode(m_indexInBlock + 1, SpecNone, Phantom, node->codeOrigin, child1, child2);
break;
@@ -1655,12 +1698,17 @@
truncateConstantsIfNecessary(node, mode);
fixEdge<Int32Use>(node->child1());
fixEdge<Int32Use>(node->child2());
+ if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
+ node->setArithMode(Arith::Unchecked);
+ else
+ node->setArithMode(Arith::CheckOverflow);
return true;
}
if (m_graph.addShouldSpeculateMachineInt(node)) {
fixEdge<MachineIntUse>(node->child1());
fixEdge<MachineIntUse>(node->child2());
+ node->setArithMode(Arith::CheckOverflow);
return true;
}