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.cpp789
1 files changed, 268 insertions, 521 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
index 4226fcc6a..980e6b447 100644
--- a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2012, 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -30,9 +30,21 @@
#include "DFGGraph.h"
#include "DFGPhase.h"
+#include "Operations.h"
namespace JSC { namespace DFG {
+SpeculatedType resultOfToPrimitive(SpeculatedType type)
+{
+ if (type & SpecObject) {
+ // Objects get turned into strings. So if the input has hints of objectness,
+ // the output will have hinsts of stringiness.
+ return mergeSpeculations(type & ~SpecObject, SpecString);
+ }
+
+ return type;
+}
+
class PredictionPropagationPhase : public Phase {
public:
PredictionPropagationPhase(Graph& graph)
@@ -42,6 +54,9 @@ public:
bool run()
{
+ ASSERT(m_graph.m_form == ThreadedCPS);
+ ASSERT(m_graph.m_unificationState == GloballyUnified);
+
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
m_count = 0;
#endif
@@ -69,13 +84,10 @@ public:
do {
m_changed = false;
doRoundOfDoubleVoting();
- propagateForward();
if (!m_changed)
break;
-
m_changed = false;
- doRoundOfDoubleVoting();
- propagateBackward();
+ propagateForward();
} while (m_changed);
return true;
@@ -84,85 +96,24 @@ public:
private:
bool setPrediction(SpeculatedType prediction)
{
- ASSERT(m_graph[m_compileIndex].hasResult());
+ ASSERT(m_currentNode->hasResult());
// setPrediction() is used when we know that there is no way that we can change
// our minds about what the prediction is going to be. There is no semantic
// difference between setPrediction() and mergeSpeculation() other than the
// increased checking to validate this property.
- ASSERT(m_graph[m_compileIndex].prediction() == SpecNone || m_graph[m_compileIndex].prediction() == prediction);
+ ASSERT(m_currentNode->prediction() == SpecNone || m_currentNode->prediction() == prediction);
- return m_graph[m_compileIndex].predict(prediction);
+ return m_currentNode->predict(prediction);
}
bool mergePrediction(SpeculatedType prediction)
{
- ASSERT(m_graph[m_compileIndex].hasResult());
+ ASSERT(m_currentNode->hasResult());
- return m_graph[m_compileIndex].predict(prediction);
- }
-
- bool isNotNegZero(NodeIndex nodeIndex)
- {
- if (!m_graph.isNumberConstant(nodeIndex))
- return false;
- double value = m_graph.valueOfNumberConstant(nodeIndex);
- return !value && 1.0 / value < 0.0;
- }
-
- bool isNotZero(NodeIndex nodeIndex)
- {
- if (!m_graph.isNumberConstant(nodeIndex))
- 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);
+ return m_currentNode->predict(prediction);
}
- 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)
{
if (!isNumberSpeculation(value))
@@ -177,16 +128,12 @@ private:
return speculatedDoubleTypeForPrediction(mergeSpeculations(left, right));
}
- void propagate(Node& node)
+ void propagate(Node* node)
{
- if (!node.shouldGenerate())
- return;
-
- NodeType op = node.op();
- NodeFlags flags = node.flags() & NodeBackPropMask;
+ NodeType op = node->op();
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
- dataLogF(" %s @%u: %s ", Graph::opName(op), m_compileIndex, nodeFlagsAsString(flags));
+ dataLog(" ", Graph::opName(op), " ", m_currentNode, ": ", NodeFlagsDump(node->flags()), " ");
#endif
bool changed = false;
@@ -194,37 +141,21 @@ private:
switch (op) {
case JSConstant:
case WeakJSConstant: {
- changed |= setPrediction(speculationFromValue(m_graph.valueOfJSConstant(m_compileIndex)));
+ changed |= setPrediction(speculationFromValue(m_graph.valueOfJSConstant(node)));
break;
}
case GetLocal: {
- VariableAccessData* variableAccessData = node.variableAccessData();
+ VariableAccessData* variableAccessData = node->variableAccessData();
SpeculatedType prediction = variableAccessData->prediction();
if (prediction)
changed |= mergePrediction(prediction);
-
- changed |= variableAccessData->mergeFlags(flags);
break;
}
case SetLocal: {
- VariableAccessData* variableAccessData = node.variableAccessData();
- changed |= variableAccessData->predict(m_graph[node.child1()].prediction());
-
- // Assume conservatively that a SetLocal implies that the value may flow through a loop,
- // and so we would have overflow leading to the program "observing" numbers even if all
- // users of the value are doing toInt32. It might be worthwhile to revisit this at some
- // point and actually check if the data flow involves loops, but right now I don't think
- // we have evidence that this would be beneficial for benchmarks.
- changed |= m_graph[node.child1()].mergeFlags(variableAccessData->flags() | NodeUsedAsNumber);
- break;
- }
-
- case Flush: {
- // Make sure that the analysis knows that flushed locals escape.
- VariableAccessData* variableAccessData = node.variableAccessData();
- changed |= variableAccessData->mergeFlags(NodeUsedAsValue);
+ VariableAccessData* variableAccessData = node->variableAccessData();
+ changed |= variableAccessData->predict(node->child1()->prediction());
break;
}
@@ -233,69 +164,57 @@ private:
case BitXor:
case BitRShift:
case BitLShift:
- case BitURShift: {
+ case BitURShift:
+ case ArithIMul: {
changed |= setPrediction(SpecInt32);
- flags |= NodeUsedAsInt;
- flags &= ~(NodeUsedAsNumber | NodeNeedsNegZero | NodeUsedAsOther);
- changed |= m_graph[node.child1()].mergeFlags(flags);
- changed |= m_graph[node.child2()].mergeFlags(flags);
break;
}
case ValueToInt32: {
changed |= setPrediction(SpecInt32);
- flags |= NodeUsedAsInt;
- flags &= ~(NodeUsedAsNumber | NodeNeedsNegZero | NodeUsedAsOther);
- changed |= m_graph[node.child1()].mergeFlags(flags);
break;
}
- case ArrayPop: {
- changed |= mergePrediction(node.getHeapPrediction());
- changed |= mergeDefaultFlags(node);
- break;
- }
-
- case ArrayPush: {
- changed |= mergePrediction(node.getHeapPrediction());
- changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue);
- changed |= m_graph[node.child2()].mergeFlags(NodeUsedAsValue);
- break;
- }
-
+ case ArrayPop:
+ case ArrayPush:
case RegExpExec:
- case RegExpTest: {
- changed |= mergePrediction(node.getHeapPrediction());
- changed |= mergeDefaultFlags(node);
+ case RegExpTest:
+ case GetById:
+ case GetByIdFlush:
+ case GetMyArgumentByValSafe:
+ case GetByOffset:
+ case Call:
+ case Construct:
+ case GetGlobalVar:
+ case GetScopedVar:
+ case Resolve:
+ case ResolveBase:
+ case ResolveBaseStrictPut:
+ case ResolveGlobal: {
+ changed |= setPrediction(node->getHeapPrediction());
break;
}
case StringCharCodeAt: {
- changed |= mergePrediction(SpecInt32);
- changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue);
- changed |= m_graph[node.child2()].mergeFlags(NodeUsedAsNumber | NodeUsedAsOther | NodeUsedAsInt);
+ changed |= setPrediction(SpecInt32);
break;
}
case UInt32ToNumber: {
- if (nodeCanSpeculateInteger(node.arithNodeFlags()))
+ if (nodeCanSpeculateInteger(node->arithNodeFlags()))
changed |= mergePrediction(SpecInt32);
else
changed |= mergePrediction(SpecNumber);
-
- changed |= m_graph[node.child1()].mergeFlags(flags);
break;
}
case ValueAdd: {
- SpeculatedType left = m_graph[node.child1()].prediction();
- SpeculatedType right = m_graph[node.child2()].prediction();
-
- AddSpeculationMode mode = DontSpeculateInteger;
+ SpeculatedType left = node->child1()->prediction();
+ SpeculatedType right = node->child2()->prediction();
if (left && right) {
if (isNumberSpeculationExpectingDefined(left) && isNumberSpeculationExpectingDefined(right)) {
- if ((mode = m_graph.addSpeculationMode(node)) != DontSpeculateInteger)
+ if (m_graph.addSpeculationMode(node) != DontSpeculateInteger)
changed |= mergePrediction(SpecInt32);
else
changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
@@ -305,107 +224,62 @@ private:
} else
changed |= mergePrediction(SpecString | SpecInt32 | SpecDouble);
}
-
- if (isNotNegZero(node.child1().index()) || isNotNegZero(node.child2().index()))
- flags &= ~NodeNeedsNegZero;
- if (m_graph[node.child1()].hasNumberResult() || m_graph[node.child2()].hasNumberResult())
- flags &= ~NodeUsedAsOther;
-
- if (mode != SpeculateInteger)
- flags |= NodeUsedAsNumber;
-
- changed |= m_graph[node.child1()].mergeFlags(flags);
- changed |= m_graph[node.child2()].mergeFlags(flags);
break;
}
case ArithAdd: {
- SpeculatedType left = m_graph[node.child1()].prediction();
- SpeculatedType right = m_graph[node.child2()].prediction();
-
- AddSpeculationMode mode = DontSpeculateInteger;
+ SpeculatedType left = node->child1()->prediction();
+ SpeculatedType right = node->child2()->prediction();
if (left && right) {
- if ((mode = m_graph.addSpeculationMode(node)) != DontSpeculateInteger)
+ if (m_graph.addSpeculationMode(node) != DontSpeculateInteger)
changed |= mergePrediction(SpecInt32);
else
changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
}
-
- if (isNotNegZero(node.child1().index()) || isNotNegZero(node.child2().index()))
- flags &= ~NodeNeedsNegZero;
- flags &= ~NodeUsedAsOther;
-
- if (mode != SpeculateInteger)
- flags |= NodeUsedAsNumber;
-
- changed |= m_graph[node.child1()].mergeFlags(flags);
- changed |= m_graph[node.child2()].mergeFlags(flags);
break;
}
case ArithSub: {
- SpeculatedType left = m_graph[node.child1()].prediction();
- SpeculatedType right = m_graph[node.child2()].prediction();
-
- AddSpeculationMode mode = DontSpeculateInteger;
+ SpeculatedType left = node->child1()->prediction();
+ SpeculatedType right = node->child2()->prediction();
if (left && right) {
- if ((mode = m_graph.addSpeculationMode(node)) != DontSpeculateInteger)
+ if (m_graph.addSpeculationMode(node) != DontSpeculateInteger)
changed |= mergePrediction(SpecInt32);
else
changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
}
-
- if (isNotZero(node.child1().index()) || isNotZero(node.child2().index()))
- flags &= ~NodeNeedsNegZero;
- flags &= ~NodeUsedAsOther;
-
- if (mode != SpeculateInteger)
- flags |= NodeUsedAsNumber;
-
- changed |= m_graph[node.child1()].mergeFlags(flags);
- changed |= m_graph[node.child2()].mergeFlags(flags);
break;
}
case ArithNegate:
- if (m_graph[node.child1()].prediction()) {
+ if (node->child1()->prediction()) {
if (m_graph.negateShouldSpeculateInteger(node))
changed |= mergePrediction(SpecInt32);
else
- changed |= mergePrediction(speculatedDoubleTypeForPrediction(m_graph[node.child1()].prediction()));
+ changed |= mergePrediction(speculatedDoubleTypeForPrediction(node->child1()->prediction()));
}
-
- flags &= ~NodeUsedAsOther;
-
- changed |= m_graph[node.child1()].mergeFlags(flags);
break;
case ArithMin:
case ArithMax: {
- SpeculatedType left = m_graph[node.child1()].prediction();
- SpeculatedType right = m_graph[node.child2()].prediction();
+ SpeculatedType left = node->child1()->prediction();
+ SpeculatedType right = node->child2()->prediction();
if (left && right) {
- if (Node::shouldSpeculateIntegerForArithmetic(m_graph[node.child1()], m_graph[node.child2()])
- && nodeCanSpeculateInteger(node.arithNodeFlags()))
+ if (Node::shouldSpeculateIntegerForArithmetic(node->child1().node(), node->child2().node())
+ && nodeCanSpeculateInteger(node->arithNodeFlags()))
changed |= mergePrediction(SpecInt32);
else
changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
}
-
- flags |= NodeUsedAsNumber;
- flags &= ~NodeUsedAsOther;
-
- changed |= m_graph[node.child1()].mergeFlags(flags);
- changed |= m_graph[node.child2()].mergeFlags(flags);
break;
}
case ArithMul: {
- SpeculatedType left = m_graph[node.child1()].prediction();
- SpeculatedType right = m_graph[node.child2()].prediction();
+ SpeculatedType left = node->child1()->prediction();
+ SpeculatedType right = node->child2()->prediction();
if (left && right) {
if (m_graph.mulShouldSpeculateInteger(node))
@@ -413,90 +287,49 @@ private:
else
changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
}
-
- // 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 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;
}
case ArithDiv: {
- SpeculatedType left = m_graph[node.child1()].prediction();
- SpeculatedType right = m_graph[node.child2()].prediction();
+ SpeculatedType left = node->child1()->prediction();
+ SpeculatedType right = node->child2()->prediction();
if (left && right) {
- if (Node::shouldSpeculateIntegerForArithmetic(m_graph[node.child1()], m_graph[node.child2()])
- && nodeCanSpeculateInteger(node.arithNodeFlags()))
+ if (Node::shouldSpeculateIntegerForArithmetic(node->child1().node(), node->child2().node())
+ && nodeCanSpeculateInteger(node->arithNodeFlags()))
changed |= mergePrediction(SpecInt32);
else
changed |= mergePrediction(SpecDouble);
}
-
- // 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, 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();
+ SpeculatedType left = node->child1()->prediction();
+ SpeculatedType right = node->child2()->prediction();
if (left && right) {
- if (Node::shouldSpeculateIntegerForArithmetic(m_graph[node.child1()], m_graph[node.child2()])
- && nodeCanSpeculateInteger(node.arithNodeFlags()))
+ if (Node::shouldSpeculateIntegerForArithmetic(node->child1().node(), node->child2().node())
+ && 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;
}
case ArithSqrt: {
changed |= setPrediction(SpecDouble);
- flags |= NodeUsedAsNumber | NodeNeedsNegZero;
- flags &= ~NodeUsedAsOther;
- changed |= m_graph[node.child1()].mergeFlags(flags);
break;
}
case ArithAbs: {
- SpeculatedType child = m_graph[node.child1()].prediction();
+ SpeculatedType child = node->child1()->prediction();
if (isInt32SpeculationForArithmetic(child)
- && nodeCanSpeculateInteger(node.arithNodeFlags()))
+ && nodeCanSpeculateInteger(node->arithNodeFlags()))
changed |= mergePrediction(SpecInt32);
else
changed |= mergePrediction(speculatedDoubleTypeForPrediction(child));
-
- changed |= m_graph[node.child1()].mergeFlags(flags);
break;
}
@@ -506,7 +339,9 @@ private:
case CompareGreater:
case CompareGreaterEq:
case CompareEq:
+ case CompareEqConstant:
case CompareStrictEq:
+ case CompareStrictEqConstant:
case InstanceOf:
case IsUndefined:
case IsBoolean:
@@ -515,36 +350,20 @@ private:
case IsObject:
case IsFunction: {
changed |= setPrediction(SpecBoolean);
- changed |= mergeDefaultFlags(node);
break;
}
-
- case GetById: {
- changed |= mergePrediction(node.getHeapPrediction());
- changed |= mergeDefaultFlags(node);
+
+ case TypeOf: {
+ changed |= setPrediction(SpecString);
break;
}
-
- case GetByIdFlush:
- changed |= mergePrediction(node.getHeapPrediction());
- changed |= mergeDefaultFlags(node);
- break;
-
+
case GetByVal: {
- if (m_graph[node.child1()].shouldSpeculateFloat32Array()
- || m_graph[node.child1()].shouldSpeculateFloat64Array())
+ if (node->child1()->shouldSpeculateFloat32Array()
+ || node->child1()->shouldSpeculateFloat64Array())
changed |= mergePrediction(SpecDouble);
else
- changed |= mergePrediction(node.getHeapPrediction());
-
- changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue);
- changed |= m_graph[node.child2()].mergeFlags(NodeUsedAsNumber | NodeUsedAsOther | NodeUsedAsInt);
- break;
- }
-
- case GetMyArgumentByValSafe: {
- changed |= mergePrediction(node.getHeapPrediction());
- changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsNumber | NodeUsedAsOther | NodeUsedAsInt);
+ changed |= mergePrediction(node->getHeapPrediction());
break;
}
@@ -559,63 +378,24 @@ private:
case AllocatePropertyStorage:
case ReallocatePropertyStorage: {
changed |= setPrediction(SpecOther);
- changed |= mergeDefaultFlags(node);
break;
}
- case GetByOffset: {
- changed |= mergePrediction(node.getHeapPrediction());
- changed |= mergeDefaultFlags(node);
- break;
- }
-
- case Call:
- case Construct: {
- changed |= mergePrediction(node.getHeapPrediction());
- for (unsigned childIdx = node.firstChild();
- childIdx < node.firstChild() + node.numChildren();
- ++childIdx) {
- Edge edge = m_graph.m_varArgChildren[childIdx];
- changed |= m_graph[edge].mergeFlags(NodeUsedAsValue);
- }
- break;
- }
-
case ConvertThis: {
- SpeculatedType prediction = m_graph[node.child1()].prediction();
+ SpeculatedType prediction = node->child1()->prediction();
if (prediction) {
- if (prediction & ~SpecObjectMask) {
- prediction &= SpecObjectMask;
+ if (prediction & ~SpecObject) {
+ prediction &= SpecObject;
prediction = mergeSpeculations(prediction, SpecObjectOther);
}
changed |= mergePrediction(prediction);
}
- changed |= mergeDefaultFlags(node);
break;
}
- case GetGlobalVar: {
- changed |= mergePrediction(node.getHeapPrediction());
- break;
- }
-
- case PutGlobalVar:
- case PutGlobalVarCheck: {
- changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue);
- break;
- }
-
- case GetScopedVar:
- case Resolve:
- case ResolveBase:
- case ResolveBaseStrictPut:
- case ResolveGlobal: {
- SpeculatedType prediction = node.getHeapPrediction();
- changed |= mergePrediction(prediction);
- break;
- }
-
- case GetScope: {
+ case GetMyScope:
+ case SkipTopScope:
+ case SkipScope: {
changed |= setPrediction(SpecCellOther);
break;
}
@@ -628,88 +408,60 @@ private:
case CreateThis:
case NewObject: {
changed |= setPrediction(SpecFinalObject);
- changed |= mergeDefaultFlags(node);
- break;
- }
-
- case NewArray: {
- changed |= setPrediction(SpecArray);
- for (unsigned childIdx = node.firstChild();
- childIdx < node.firstChild() + node.numChildren();
- ++childIdx) {
- Edge edge = m_graph.m_varArgChildren[childIdx];
- changed |= m_graph[edge].mergeFlags(NodeUsedAsValue);
- }
- break;
- }
-
- case NewArrayWithSize: {
- changed |= setPrediction(SpecArray);
- changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue | NodeUsedAsInt);
break;
}
+ case NewArray:
+ case NewArrayWithSize:
case NewArrayBuffer: {
changed |= setPrediction(SpecArray);
break;
}
- case NewRegexp: {
+ case NewRegexp:
+ case CreateActivation: {
changed |= setPrediction(SpecObjectOther);
break;
}
- case StringCharAt: {
+ case StringFromCharCode: {
changed |= setPrediction(SpecString);
- changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue);
- changed |= m_graph[node.child2()].mergeFlags(NodeUsedAsNumber | NodeUsedAsOther | NodeUsedAsInt);
+ changed |= node->child1()->mergeFlags(NodeUsedAsNumber | NodeUsedAsInt);
break;
}
-
- case StrCat: {
+ case StringCharAt:
+ case ToString:
+ case MakeRope: {
changed |= setPrediction(SpecString);
- for (unsigned childIdx = node.firstChild();
- childIdx < node.firstChild() + node.numChildren();
- ++childIdx)
- changed |= m_graph[m_graph.m_varArgChildren[childIdx]].mergeFlags(NodeUsedAsNumber | NodeUsedAsOther);
break;
}
case ToPrimitive: {
- SpeculatedType child = m_graph[node.child1()].prediction();
- if (child) {
- if (isObjectSpeculation(child)) {
- // I'd love to fold this case into the case below, but I can't, because
- // removing SpecObjectMask from something that only has an object
- // prediction and nothing else means we have an ill-formed SpeculatedType
- // (strong predict-none). This should be killed once we remove all traces
- // of static (aka weak) predictions.
- changed |= mergePrediction(SpecString);
- } else if (child & SpecObjectMask) {
- // Objects get turned into strings. So if the input has hints of objectness,
- // the output will have hinsts of stringiness.
- changed |= mergePrediction(
- mergeSpeculations(child & ~SpecObjectMask, SpecString));
- } else
- changed |= mergePrediction(child);
- }
- changed |= m_graph[node.child1()].mergeFlags(flags);
+ SpeculatedType child = node->child1()->prediction();
+ if (child)
+ changed |= mergePrediction(resultOfToPrimitive(child));
break;
}
- case CreateActivation: {
- changed |= setPrediction(SpecObjectOther);
+ case NewStringObject: {
+ changed |= setPrediction(SpecStringObject);
break;
}
case CreateArguments: {
- // At this stage we don't try to predict whether the arguments are ours or
- // someone else's. We could, but we don't, yet.
changed |= setPrediction(SpecArguments);
break;
}
- case NewFunction:
+ case NewFunction: {
+ SpeculatedType child = node->child1()->prediction();
+ if (child & SpecEmpty)
+ changed |= mergePrediction((child & ~SpecEmpty) | SpecFunction);
+ else
+ changed |= mergePrediction(child);
+ break;
+ }
+
case NewFunctionNoCheck:
case NewFunctionExpression: {
changed |= setPrediction(SpecFunction);
@@ -719,6 +471,7 @@ private:
case PutByValAlias:
case GetArrayLength:
case Int32ToDouble:
+ case ForwardInt32ToDouble:
case DoubleAsInt32:
case GetLocalUnlinked:
case GetMyArgumentsLength:
@@ -728,45 +481,40 @@ private:
case CheckArray:
case Arrayify:
case ArrayifyToStructure:
- case Identity: {
+ case MovHint:
+ case MovHintAndCheck:
+ case ZombieHint: {
// This node should never be visible at this stage of compilation. It is
// inserted by fixup(), which follows this phase.
CRASH();
break;
}
- case PutByVal:
- changed |= m_graph[m_graph.varArgChild(node, 0)].mergeFlags(NodeUsedAsValue);
- changed |= m_graph[m_graph.varArgChild(node, 1)].mergeFlags(NodeUsedAsNumber | NodeUsedAsOther | NodeUsedAsInt);
- changed |= m_graph[m_graph.varArgChild(node, 2)].mergeFlags(NodeUsedAsValue);
- break;
-
- case PutScopedVar:
- changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue);
- changed |= m_graph[node.child3()].mergeFlags(NodeUsedAsValue);
- break;
-
- case Return:
- case Throw:
- changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue);
+ case Phi:
+ // Phis should not be visible here since we're iterating the all-but-Phi's
+ // part of basic blocks.
+ CRASH();
break;
- case PutById:
- case PutByIdDirect:
- changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue);
- changed |= m_graph[node.child2()].mergeFlags(NodeUsedAsValue);
+ case GetScope:
+ changed |= setPrediction(SpecCellOther);
break;
- case PutByOffset:
- changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue);
- changed |= m_graph[node.child3()].mergeFlags(NodeUsedAsValue);
- break;
-
- case Phi:
+ case Identity:
+ changed |= mergePrediction(node->child1()->prediction());
break;
#ifndef NDEBUG
// These get ignored because they don't return anything.
+ case PutByVal:
+ case PutScopedVar:
+ case Return:
+ case Throw:
+ case PutById:
+ case PutByIdDirect:
+ case PutByOffset:
+ case SetCallee:
+ case SetMyScope:
case DFG::Jump:
case Branch:
case Breakpoint:
@@ -775,6 +523,7 @@ private:
case ForceOSRExit:
case SetArgument:
case CheckStructure:
+ case CheckExecutable:
case ForwardCheckStructure:
case StructureTransitionWatchpoint:
case ForwardStructureTransitionWatchpoint:
@@ -782,18 +531,22 @@ private:
case PutStructure:
case TearOffActivation:
case TearOffArguments:
- case CheckNumber:
case CheckArgumentsNotCreated:
case GlobalVarWatchpoint:
case GarbageValue:
- case InheritorIDWatchpoint:
- changed |= mergeDefaultFlags(node);
+ case AllocationProfileWatchpoint:
+ case Phantom:
+ case PutGlobalVar:
+ case PutGlobalVarCheck:
+ case CheckWatchdogTimer:
break;
// These gets ignored because it doesn't do anything.
- case Phantom:
case InlineStart:
case Nop:
+ case CountExecution:
+ case PhantomLocal:
+ case Flush:
break;
case LastNodeType:
@@ -801,49 +554,32 @@ private:
break;
#else
default:
- changed |= mergeDefaultFlags(node);
break;
#endif
}
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
- dataLogF("%s\n", speculationToString(m_graph[m_compileIndex].prediction()));
+ dataLog(SpeculationDump(node->prediction()), "\n");
#endif
m_changed |= changed;
}
- bool mergeDefaultFlags(Node& node)
- {
- bool changed = false;
- if (node.flags() & NodeHasVarArgs) {
- for (unsigned childIdx = node.firstChild();
- childIdx < node.firstChild() + node.numChildren();
- childIdx++) {
- if (!!m_graph.m_varArgChildren[childIdx])
- changed |= m_graph[m_graph.m_varArgChildren[childIdx]].mergeFlags(NodeUsedAsValue);
- }
- } else {
- if (!node.child1())
- return changed;
- changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue);
- if (!node.child2())
- return changed;
- changed |= m_graph[node.child2()].mergeFlags(NodeUsedAsValue);
- if (!node.child3())
- return changed;
- changed |= m_graph[node.child3()].mergeFlags(NodeUsedAsValue);
- }
- return changed;
- }
-
void propagateForward()
{
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
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]);
+ for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) {
+ BasicBlock* block = m_graph.m_blocks[blockIndex].get();
+ if (!block)
+ continue;
+ ASSERT(block->isReachable);
+ for (unsigned i = 0; i < block->size(); ++i) {
+ m_currentNode = block->at(i);
+ propagate(m_currentNode);
+ }
+ }
}
void propagateBackward()
@@ -851,147 +587,158 @@ private:
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
dataLogF("Propagating predictions backward [%u]\n", ++m_count);
#endif
- for (m_compileIndex = m_graph.size(); m_compileIndex-- > 0;)
- propagate(m_graph[m_compileIndex]);
+ for (BlockIndex blockIndex = m_graph.m_blocks.size(); blockIndex--;) {
+ BasicBlock* block = m_graph.m_blocks[blockIndex].get();
+ if (!block)
+ continue;
+ ASSERT(block->isReachable);
+ for (unsigned i = block->size(); i--;) {
+ m_currentNode = block->at(i);
+ propagate(m_currentNode);
+ }
+ }
}
- void doRoundOfDoubleVoting()
+ void doDoubleVoting(Node* node)
{
-#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
- 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();
- for (m_compileIndex = 0; m_compileIndex < m_graph.size(); ++m_compileIndex) {
- Node& node = m_graph[m_compileIndex];
- switch (node.op()) {
- case ValueAdd:
- case ArithAdd:
- case ArithSub: {
- SpeculatedType left = m_graph[node.child1()].prediction();
- SpeculatedType right = m_graph[node.child2()].prediction();
+ switch (node->op()) {
+ case ValueAdd:
+ case ArithAdd:
+ case ArithSub: {
+ SpeculatedType left = node->child1()->prediction();
+ SpeculatedType right = node->child2()->prediction();
- DoubleBallot ballot;
+ DoubleBallot ballot;
- if (isNumberSpeculationExpectingDefined(left) && isNumberSpeculationExpectingDefined(right)
- && !m_graph.addShouldSpeculateInteger(node))
- ballot = VoteDouble;
- else
- ballot = VoteValue;
+ if (isNumberSpeculationExpectingDefined(left) && isNumberSpeculationExpectingDefined(right)
+ && !m_graph.addShouldSpeculateInteger(node))
+ ballot = VoteDouble;
+ else
+ ballot = VoteValue;
- m_graph.vote(node.child1(), ballot);
- m_graph.vote(node.child2(), ballot);
- break;
- }
+ m_graph.voteNode(node->child1(), ballot);
+ m_graph.voteNode(node->child2(), ballot);
+ break;
+ }
- case ArithMul: {
- SpeculatedType left = m_graph[node.child1()].prediction();
- SpeculatedType right = m_graph[node.child2()].prediction();
+ case ArithMul: {
+ SpeculatedType left = node->child1()->prediction();
+ SpeculatedType right = node->child2()->prediction();
- DoubleBallot ballot;
+ DoubleBallot ballot;
- if (isNumberSpeculation(left) && isNumberSpeculation(right)
- && !m_graph.mulShouldSpeculateInteger(node))
- ballot = VoteDouble;
- else
- ballot = VoteValue;
+ if (isNumberSpeculation(left) && isNumberSpeculation(right)
+ && !m_graph.mulShouldSpeculateInteger(node))
+ ballot = VoteDouble;
+ else
+ ballot = VoteValue;
- m_graph.vote(node.child1(), ballot);
- m_graph.vote(node.child2(), ballot);
- break;
- }
+ m_graph.voteNode(node->child1(), ballot);
+ m_graph.voteNode(node->child2(), ballot);
+ break;
+ }
- case ArithMin:
- case ArithMax:
- case ArithMod:
- case ArithDiv: {
- SpeculatedType left = m_graph[node.child1()].prediction();
- SpeculatedType right = m_graph[node.child2()].prediction();
+ case ArithMin:
+ case ArithMax:
+ case ArithMod:
+ case ArithDiv: {
+ SpeculatedType left = node->child1()->prediction();
+ SpeculatedType right = node->child2()->prediction();
- DoubleBallot ballot;
+ DoubleBallot ballot;
- if (isNumberSpeculation(left) && isNumberSpeculation(right)
- && !(Node::shouldSpeculateIntegerForArithmetic(m_graph[node.child1()], m_graph[node.child1()])
- && node.canSpeculateInteger()))
- ballot = VoteDouble;
- else
- ballot = VoteValue;
+ if (isNumberSpeculation(left) && isNumberSpeculation(right)
+ && !(Node::shouldSpeculateIntegerForArithmetic(node->child1().node(), node->child2().node()) && node->canSpeculateInteger()))
+ ballot = VoteDouble;
+ else
+ ballot = VoteValue;
- m_graph.vote(node.child1(), ballot);
- m_graph.vote(node.child2(), ballot);
- break;
- }
+ m_graph.voteNode(node->child1(), ballot);
+ m_graph.voteNode(node->child2(), ballot);
+ break;
+ }
- case ArithAbs:
- DoubleBallot ballot;
- if (!(m_graph[node.child1()].shouldSpeculateIntegerForArithmetic()
- && node.canSpeculateInteger()))
- ballot = VoteDouble;
- else
- ballot = VoteValue;
+ case ArithAbs:
+ DoubleBallot ballot;
+ if (!(node->child1()->shouldSpeculateIntegerForArithmetic() && node->canSpeculateInteger()))
+ ballot = VoteDouble;
+ else
+ ballot = VoteValue;
- m_graph.vote(node.child1(), ballot);
- break;
+ m_graph.voteNode(node->child1(), ballot);
+ break;
- case ArithSqrt:
- m_graph.vote(node.child1(), VoteDouble);
- break;
+ case ArithSqrt:
+ m_graph.voteNode(node->child1(), VoteDouble);
+ break;
- case SetLocal: {
- SpeculatedType prediction = m_graph[node.child1()].prediction();
- if (isDoubleSpeculation(prediction))
- node.variableAccessData()->vote(VoteDouble);
- else if (!isNumberSpeculation(prediction) || isInt32Speculation(prediction))
- node.variableAccessData()->vote(VoteValue);
- break;
- }
+ case SetLocal: {
+ SpeculatedType prediction = node->child1()->prediction();
+ if (isDoubleSpeculation(prediction))
+ node->variableAccessData()->vote(VoteDouble);
+ else if (!isNumberSpeculation(prediction) || isInt32Speculation(prediction))
+ node->variableAccessData()->vote(VoteValue);
+ 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;
- }
+ 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.voteNode(child1, VoteValue);
+ m_graph.voteNode(child2, VoteValue);
+ switch (node->arrayMode().type()) {
+ case Array::Double:
+ m_graph.voteNode(child3, VoteDouble);
break;
- }
-
default:
- m_graph.vote(node, VoteValue);
+ m_graph.voteNode(child3, VoteValue);
break;
}
+ break;
+ }
+
+ default:
+ m_graph.voteChildren(node, VoteValue);
+ break;
+ }
+ }
+
+ void doRoundOfDoubleVoting()
+ {
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+ 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();
+ for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) {
+ BasicBlock* block = m_graph.m_blocks[blockIndex].get();
+ if (!block)
+ continue;
+ ASSERT(block->isReachable);
+ for (unsigned i = 0; i < block->size(); ++i) {
+ m_currentNode = block->at(i);
+ doDoubleVoting(m_currentNode);
+ }
}
for (unsigned i = 0; i < m_graph.m_variableAccessData.size(); ++i) {
VariableAccessData* variableAccessData = &m_graph.m_variableAccessData[i];
if (!variableAccessData->isRoot())
continue;
- if (operandIsArgument(variableAccessData->local())
- || variableAccessData->isCaptured())
- continue;
m_changed |= variableAccessData->tallyVotesForShouldUseDoubleFormat();
}
for (unsigned i = 0; i < m_graph.m_argumentPositions.size(); ++i)
- m_changed |= m_graph.m_argumentPositions[i].mergeArgumentAwareness();
+ m_changed |= m_graph.m_argumentPositions[i].mergeArgumentPredictionAwareness();
for (unsigned i = 0; i < m_graph.m_variableAccessData.size(); ++i) {
VariableAccessData* variableAccessData = &m_graph.m_variableAccessData[i];
if (!variableAccessData->isRoot())
continue;
- if (operandIsArgument(variableAccessData->local())
- || variableAccessData->isCaptured())
- continue;
m_changed |= variableAccessData->makePredictionForDoubleFormat();
}
}
- NodeIndex m_compileIndex;
+ Node* m_currentNode;
bool m_changed;
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)