summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp')
-rw-r--r--Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp188
1 files changed, 139 insertions, 49 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
index 3e8ead5c6..4b8a17285 100644
--- a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
@@ -116,6 +116,52 @@ private:
return false;
return !!m_graph.valueOfNumberConstant(nodeIndex);
}
+
+ bool isWithinPowerOfTwoForConstant(Node& node, int power)
+ {
+ JSValue immediateValue = node.valueOfJSConstant(codeBlock());
+ if (!immediateValue.isInt32())
+ return false;
+ int32_t intImmediate = immediateValue.asInt32();
+ return intImmediate > -(1 << power) && intImmediate < (1 << power);
+ }
+
+ bool isWithinPowerOfTwoNonRecursive(NodeIndex nodeIndex, int power)
+ {
+ Node& node = m_graph[nodeIndex];
+ if (node.op() != JSConstant)
+ return false;
+ return isWithinPowerOfTwoForConstant(node, power);
+ }
+
+ bool isWithinPowerOfTwo(NodeIndex nodeIndex, int power)
+ {
+ Node& node = m_graph[nodeIndex];
+ switch (node.op()) {
+ case JSConstant: {
+ return isWithinPowerOfTwoForConstant(node, power);
+ }
+
+ case BitAnd: {
+ return isWithinPowerOfTwoNonRecursive(node.child1().index(), power)
+ || isWithinPowerOfTwoNonRecursive(node.child2().index(), power);
+ }
+
+ case BitRShift:
+ case BitURShift: {
+ Node& shiftAmount = m_graph[node.child2()];
+ if (shiftAmount.op() != JSConstant)
+ return false;
+ JSValue immediateValue = shiftAmount.valueOfJSConstant(codeBlock());
+ if (!immediateValue.isInt32())
+ return false;
+ return immediateValue > 32 - power;
+ }
+
+ default:
+ return false;
+ }
+ }
SpeculatedType speculatedDoubleTypeForPrediction(SpeculatedType value)
{
@@ -140,7 +186,7 @@ private:
NodeFlags flags = node.flags() & NodeBackPropMask;
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
- dataLog(" %s @%u: %s ", Graph::opName(op), m_compileIndex, nodeFlagsAsString(flags));
+ dataLogF(" %s @%u: %s ", Graph::opName(op), m_compileIndex, nodeFlagsAsString(flags));
#endif
bool changed = false;
@@ -184,7 +230,7 @@ private:
case BitURShift: {
changed |= setPrediction(SpecInt32);
flags |= NodeUsedAsInt;
- flags &= ~(NodeUsedAsNumber | NodeNeedsNegZero);
+ flags &= ~(NodeUsedAsNumber | NodeNeedsNegZero | NodeUsedAsOther);
changed |= m_graph[node.child1()].mergeFlags(flags);
changed |= m_graph[node.child2()].mergeFlags(flags);
break;
@@ -193,7 +239,7 @@ private:
case ValueToInt32: {
changed |= setPrediction(SpecInt32);
flags |= NodeUsedAsInt;
- flags &= ~(NodeUsedAsNumber | NodeNeedsNegZero);
+ flags &= ~(NodeUsedAsNumber | NodeNeedsNegZero | NodeUsedAsOther);
changed |= m_graph[node.child1()].mergeFlags(flags);
break;
}
@@ -221,28 +267,10 @@ private:
case StringCharCodeAt: {
changed |= mergePrediction(SpecInt32);
changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue);
- changed |= m_graph[node.child2()].mergeFlags(NodeUsedAsNumber | NodeUsedAsInt);
+ changed |= m_graph[node.child2()].mergeFlags(NodeUsedAsNumber | NodeUsedAsOther | NodeUsedAsInt);
break;
}
- case ArithMod: {
- SpeculatedType left = m_graph[node.child1()].prediction();
- SpeculatedType right = m_graph[node.child2()].prediction();
-
- if (left && right) {
- if (isInt32Speculation(mergeSpeculations(left, right))
- && nodeCanSpeculateInteger(node.arithNodeFlags()))
- changed |= mergePrediction(SpecInt32);
- else
- changed |= mergePrediction(SpecDouble);
- }
-
- flags |= NodeUsedAsValue;
- changed |= m_graph[node.child1()].mergeFlags(flags);
- changed |= m_graph[node.child2()].mergeFlags(flags);
- break;
- }
-
case UInt32ToNumber: {
if (nodeCanSpeculateInteger(node.arithNodeFlags()))
changed |= mergePrediction(SpecInt32);
@@ -258,7 +286,7 @@ private:
SpeculatedType right = m_graph[node.child2()].prediction();
if (left && right) {
- if (isNumberSpeculation(left) && isNumberSpeculation(right)) {
+ if (isNumberSpeculationExpectingDefined(left) && isNumberSpeculationExpectingDefined(right)) {
if (m_graph.addShouldSpeculateInteger(node))
changed |= mergePrediction(SpecInt32);
else
@@ -272,6 +300,8 @@ private:
if (isNotNegZero(node.child1().index()) || isNotNegZero(node.child2().index()))
flags &= ~NodeNeedsNegZero;
+ if (m_graph[node.child1()].hasNumberResult() || m_graph[node.child2()].hasNumberResult())
+ flags &= ~NodeUsedAsOther;
changed |= m_graph[node.child1()].mergeFlags(flags);
changed |= m_graph[node.child2()].mergeFlags(flags);
@@ -291,6 +321,7 @@ private:
if (isNotNegZero(node.child1().index()) || isNotNegZero(node.child2().index()))
flags &= ~NodeNeedsNegZero;
+ flags &= ~NodeUsedAsOther;
changed |= m_graph[node.child1()].mergeFlags(flags);
changed |= m_graph[node.child2()].mergeFlags(flags);
@@ -310,6 +341,7 @@ private:
if (isNotZero(node.child1().index()) || isNotZero(node.child2().index()))
flags &= ~NodeNeedsNegZero;
+ flags &= ~NodeUsedAsOther;
changed |= m_graph[node.child1()].mergeFlags(flags);
changed |= m_graph[node.child2()].mergeFlags(flags);
@@ -324,6 +356,8 @@ private:
changed |= mergePrediction(speculatedDoubleTypeForPrediction(m_graph[node.child1()].prediction()));
}
+ flags &= ~NodeUsedAsOther;
+
changed |= m_graph[node.child1()].mergeFlags(flags);
break;
@@ -333,7 +367,7 @@ private:
SpeculatedType right = m_graph[node.child2()].prediction();
if (left && right) {
- if (isInt32Speculation(mergeSpeculations(left, right))
+ if (Node::shouldSpeculateIntegerForArithmetic(m_graph[node.child1()], m_graph[node.child2()])
&& nodeCanSpeculateInteger(node.arithNodeFlags()))
changed |= mergePrediction(SpecInt32);
else
@@ -341,6 +375,8 @@ private:
}
flags |= NodeUsedAsNumber;
+ flags &= ~NodeUsedAsOther;
+
changed |= m_graph[node.child1()].mergeFlags(flags);
changed |= m_graph[node.child2()].mergeFlags(flags);
break;
@@ -359,10 +395,20 @@ private:
// As soon as a multiply happens, we can easily end up in the part
// of the double domain where the point at which you do truncation
- // can change the outcome. So, ArithMul always checks for overflow
- // no matter what, and always forces its inputs to check as well.
+ // can change the outcome. So, ArithMul always forces its inputs to
+ // check for overflow. Additionally, it will have to check for overflow
+ // itself unless we can prove that there is no way for the values
+ // produced to cause double rounding.
+
+ if (!isWithinPowerOfTwo(node.child1().index(), 22)
+ && !isWithinPowerOfTwo(node.child2().index(), 22))
+ flags |= NodeUsedAsNumber;
+
+ changed |= node.mergeFlags(flags);
flags |= NodeUsedAsNumber | NodeNeedsNegZero;
+ flags &= ~NodeUsedAsOther;
+
changed |= m_graph[node.child1()].mergeFlags(flags);
changed |= m_graph[node.child2()].mergeFlags(flags);
break;
@@ -373,7 +419,7 @@ private:
SpeculatedType right = m_graph[node.child2()].prediction();
if (left && right) {
- if (isInt32Speculation(mergeSpeculations(left, right))
+ if (Node::shouldSpeculateIntegerForArithmetic(m_graph[node.child1()], m_graph[node.child2()])
&& nodeCanSpeculateInteger(node.arithNodeFlags()))
changed |= mergePrediction(SpecInt32);
else
@@ -382,10 +428,32 @@ private:
// As soon as a multiply happens, we can easily end up in the part
// of the double domain where the point at which you do truncation
- // can change the outcome. So, ArithMul always checks for overflow
+ // can change the outcome. So, ArithDiv always checks for overflow
// no matter what, and always forces its inputs to check as well.
flags |= NodeUsedAsNumber | NodeNeedsNegZero;
+ flags &= ~NodeUsedAsOther;
+
+ changed |= m_graph[node.child1()].mergeFlags(flags);
+ changed |= m_graph[node.child2()].mergeFlags(flags);
+ break;
+ }
+
+ case ArithMod: {
+ SpeculatedType left = m_graph[node.child1()].prediction();
+ SpeculatedType right = m_graph[node.child2()].prediction();
+
+ if (left && right) {
+ if (Node::shouldSpeculateIntegerForArithmetic(m_graph[node.child1()], m_graph[node.child2()])
+ && nodeCanSpeculateInteger(node.arithNodeFlags()))
+ changed |= mergePrediction(SpecInt32);
+ else
+ changed |= mergePrediction(SpecDouble);
+ }
+
+ flags |= NodeUsedAsNumber | NodeNeedsNegZero;
+ flags &= ~NodeUsedAsOther;
+
changed |= m_graph[node.child1()].mergeFlags(flags);
changed |= m_graph[node.child2()].mergeFlags(flags);
break;
@@ -393,18 +461,20 @@ private:
case ArithSqrt: {
changed |= setPrediction(SpecDouble);
- changed |= m_graph[node.child1()].mergeFlags(flags | NodeUsedAsValue);
+ flags |= NodeUsedAsNumber | NodeNeedsNegZero;
+ flags &= ~NodeUsedAsOther;
+ changed |= m_graph[node.child1()].mergeFlags(flags);
break;
}
case ArithAbs: {
SpeculatedType child = m_graph[node.child1()].prediction();
- if (nodeCanSpeculateInteger(node.arithNodeFlags()))
- changed |= mergePrediction(child);
+ if (isInt32SpeculationForArithmetic(child)
+ && nodeCanSpeculateInteger(node.arithNodeFlags()))
+ changed |= mergePrediction(SpecInt32);
else
- changed |= setPrediction(speculatedDoubleTypeForPrediction(child));
+ changed |= mergePrediction(speculatedDoubleTypeForPrediction(child));
- flags &= ~NodeNeedsNegZero;
changed |= m_graph[node.child1()].mergeFlags(flags);
break;
}
@@ -447,13 +517,13 @@ private:
changed |= mergePrediction(node.getHeapPrediction());
changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue);
- changed |= m_graph[node.child2()].mergeFlags(NodeUsedAsNumber | NodeUsedAsInt);
+ changed |= m_graph[node.child2()].mergeFlags(NodeUsedAsNumber | NodeUsedAsOther | NodeUsedAsInt);
break;
}
case GetMyArgumentByValSafe: {
changed |= mergePrediction(node.getHeapPrediction());
- changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsNumber | NodeUsedAsInt);
+ changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsNumber | NodeUsedAsOther | NodeUsedAsInt);
break;
}
@@ -554,7 +624,7 @@ private:
case NewArrayWithSize: {
changed |= setPrediction(SpecArray);
- changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsNumber | NodeUsedAsInt);
+ changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue | NodeUsedAsInt);
break;
}
@@ -571,7 +641,7 @@ private:
case StringCharAt: {
changed |= setPrediction(SpecString);
changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue);
- changed |= m_graph[node.child2()].mergeFlags(NodeUsedAsNumber | NodeUsedAsInt);
+ changed |= m_graph[node.child2()].mergeFlags(NodeUsedAsNumber | NodeUsedAsOther | NodeUsedAsInt);
break;
}
@@ -580,7 +650,7 @@ private:
for (unsigned childIdx = node.firstChild();
childIdx < node.firstChild() + node.numChildren();
++childIdx)
- changed |= m_graph[m_graph.m_varArgChildren[childIdx]].mergeFlags(NodeUsedAsNumber);
+ changed |= m_graph[m_graph.m_varArgChildren[childIdx]].mergeFlags(NodeUsedAsNumber | NodeUsedAsOther);
break;
}
@@ -636,16 +706,17 @@ private:
case PhantomArguments:
case CheckArray:
case Arrayify:
- case ArrayifyToStructure: {
+ case ArrayifyToStructure:
+ case Identity: {
// This node should never be visible at this stage of compilation. It is
// inserted by fixup(), which follows this phase.
- ASSERT_NOT_REACHED();
+ CRASH();
break;
}
case PutByVal:
changed |= m_graph[m_graph.varArgChild(node, 0)].mergeFlags(NodeUsedAsValue);
- changed |= m_graph[m_graph.varArgChild(node, 1)].mergeFlags(NodeUsedAsNumber | NodeUsedAsInt);
+ changed |= m_graph[m_graph.varArgChild(node, 1)].mergeFlags(NodeUsedAsNumber | NodeUsedAsOther | NodeUsedAsInt);
changed |= m_graph[m_graph.varArgChild(node, 2)].mergeFlags(NodeUsedAsValue);
break;
@@ -690,6 +761,7 @@ private:
case CheckArgumentsNotCreated:
case GlobalVarWatchpoint:
case GarbageValue:
+ case InheritorIDWatchpoint:
changed |= mergeDefaultFlags(node);
break;
@@ -700,7 +772,7 @@ private:
break;
case LastNodeType:
- ASSERT_NOT_REACHED();
+ CRASH();
break;
#else
default:
@@ -710,7 +782,7 @@ private:
}
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
- dataLog("%s\n", speculationToString(m_graph[m_compileIndex].prediction()));
+ dataLogF("%s\n", speculationToString(m_graph[m_compileIndex].prediction()));
#endif
m_changed |= changed;
@@ -743,7 +815,7 @@ private:
void propagateForward()
{
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
- dataLog("Propagating predictions forward [%u]\n", ++m_count);
+ dataLogF("Propagating predictions forward [%u]\n", ++m_count);
#endif
for (m_compileIndex = 0; m_compileIndex < m_graph.size(); ++m_compileIndex)
propagate(m_graph[m_compileIndex]);
@@ -752,7 +824,7 @@ private:
void propagateBackward()
{
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
- dataLog("Propagating predictions backward [%u]\n", ++m_count);
+ dataLogF("Propagating predictions backward [%u]\n", ++m_count);
#endif
for (m_compileIndex = m_graph.size(); m_compileIndex-- > 0;)
propagate(m_graph[m_compileIndex]);
@@ -761,7 +833,7 @@ private:
void doRoundOfDoubleVoting()
{
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
- dataLog("Voting on double uses of locals [%u]\n", m_count);
+ dataLogF("Voting on double uses of locals [%u]\n", m_count);
#endif
for (unsigned i = 0; i < m_graph.m_variableAccessData.size(); ++i)
m_graph.m_variableAccessData[i].find()->clearVotes();
@@ -776,7 +848,7 @@ private:
DoubleBallot ballot;
- if (isNumberSpeculation(left) && isNumberSpeculation(right)
+ if (isNumberSpeculationExpectingDefined(left) && isNumberSpeculationExpectingDefined(right)
&& !m_graph.addShouldSpeculateInteger(node))
ballot = VoteDouble;
else
@@ -814,7 +886,7 @@ private:
DoubleBallot ballot;
if (isNumberSpeculation(left) && isNumberSpeculation(right)
- && !(Node::shouldSpeculateInteger(m_graph[node.child1()], m_graph[node.child1()])
+ && !(Node::shouldSpeculateIntegerForArithmetic(m_graph[node.child1()], m_graph[node.child1()])
&& node.canSpeculateInteger()))
ballot = VoteDouble;
else
@@ -827,7 +899,7 @@ private:
case ArithAbs:
DoubleBallot ballot;
- if (!(m_graph[node.child1()].shouldSpeculateInteger()
+ if (!(m_graph[node.child1()].shouldSpeculateIntegerForArithmetic()
&& node.canSpeculateInteger()))
ballot = VoteDouble;
else
@@ -849,6 +921,24 @@ private:
break;
}
+ case PutByVal:
+ case PutByValAlias: {
+ Edge child1 = m_graph.varArgChild(node, 0);
+ Edge child2 = m_graph.varArgChild(node, 1);
+ Edge child3 = m_graph.varArgChild(node, 2);
+ m_graph.vote(child1, VoteValue);
+ m_graph.vote(child2, VoteValue);
+ switch (node.arrayMode().type()) {
+ case Array::Double:
+ m_graph.vote(child3, VoteDouble);
+ break;
+ default:
+ m_graph.vote(child3, VoteValue);
+ break;
+ }
+ break;
+ }
+
default:
m_graph.vote(node, VoteValue);
break;