Title: [199933] trunk/Source/_javascript_Core
Revision
199933
Author
commit-qu...@webkit.org
Date
2016-04-22 16:10:27 -0700 (Fri, 22 Apr 2016)

Log Message

[JSC] PredictionPropagation should not be in the top 5 heaviest phases
https://bugs.webkit.org/show_bug.cgi?id=156891

Patch by Benjamin Poulain <bpoul...@apple.com> on 2016-04-22
Reviewed by Mark Lam.

In DFG, PredictionPropagation is often way too high in profiles.
It is a simple phase, it should not be that hot.

Most of the time is spent accessing memory. This patch attempts
to reduce that.

First, propagate() is split in processInvariants() and propagates().
The step processInvariants() sets all the types for nodes for which
the type does not depends on other nodes.

Adding processInvariants() lowers two hotspot inside PredictionPropagation:
speculationFromValue() and setPrediction().

Next, to avoid touching all the nodes at every operation, we keep
track of the nodes that actually need propagate().
The vector m_dependentNodes keeps the list of those nodes and propagate()
only need to process them at each phase.

This is a smaller gain because growing m_dependentNodes negates
some of the gains.

On 3d-cube, this moves PredictionPropagation from fifth position
to ninth. A lot of the remaining overhead is caused by double-voting
and cannot be fixed by moving stuff around.

* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::propagateToFixpoint): Deleted.
(JSC::DFG::PredictionPropagationPhase::propagate): Deleted.
(JSC::DFG::PredictionPropagationPhase::propagateForward): Deleted.
(JSC::DFG::PredictionPropagationPhase::propagateBackward): Deleted.
(JSC::DFG::PredictionPropagationPhase::doDoubleVoting): Deleted.
(JSC::DFG::PredictionPropagationPhase::doRoundOfDoubleVoting): Deleted.
(JSC::DFG::PredictionPropagationPhase::propagateThroughArgumentPositions): Deleted.

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (199932 => 199933)


--- trunk/Source/_javascript_Core/ChangeLog	2016-04-22 23:10:08 UTC (rev 199932)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-04-22 23:10:27 UTC (rev 199933)
@@ -1,3 +1,44 @@
+2016-04-22  Benjamin Poulain  <bpoul...@apple.com>
+
+        [JSC] PredictionPropagation should not be in the top 5 heaviest phases
+        https://bugs.webkit.org/show_bug.cgi?id=156891
+
+        Reviewed by Mark Lam.
+
+        In DFG, PredictionPropagation is often way too high in profiles.
+        It is a simple phase, it should not be that hot.
+
+        Most of the time is spent accessing memory. This patch attempts
+        to reduce that.
+
+        First, propagate() is split in processInvariants() and propagates().
+        The step processInvariants() sets all the types for nodes for which
+        the type does not depends on other nodes.
+
+        Adding processInvariants() lowers two hotspot inside PredictionPropagation:
+        speculationFromValue() and setPrediction().
+
+        Next, to avoid touching all the nodes at every operation, we keep
+        track of the nodes that actually need propagate().
+        The vector m_dependentNodes keeps the list of those nodes and propagate()
+        only need to process them at each phase.
+
+        This is a smaller gain because growing m_dependentNodes negates
+        some of the gains.
+
+        On 3d-cube, this moves PredictionPropagation from fifth position
+        to ninth. A lot of the remaining overhead is caused by double-voting
+        and cannot be fixed by moving stuff around.
+
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        (JSC::DFG::PredictionPropagationPhase::propagateToFixpoint): Deleted.
+        (JSC::DFG::PredictionPropagationPhase::propagate): Deleted.
+        (JSC::DFG::PredictionPropagationPhase::propagateForward): Deleted.
+        (JSC::DFG::PredictionPropagationPhase::propagateBackward): Deleted.
+        (JSC::DFG::PredictionPropagationPhase::doDoubleVoting): Deleted.
+        (JSC::DFG::PredictionPropagationPhase::doRoundOfDoubleVoting): Deleted.
+        (JSC::DFG::PredictionPropagationPhase::propagateThroughArgumentPositions): Deleted.
+
 2016-04-22  Geoffrey Garen  <gga...@apple.com>
 
         super should be available in object literals

Modified: trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (199932 => 199933)


--- trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2016-04-22 23:10:08 UTC (rev 199932)
+++ trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2016-04-22 23:10:27 UTC (rev 199933)
@@ -34,6 +34,10 @@
 
 namespace JSC { namespace DFG {
 
+namespace {
+
+bool verboseFixPointLoops = false;
+
 class PredictionPropagationPhase : public Phase {
 public:
     PredictionPropagationPhase(Graph& graph)
@@ -48,6 +52,8 @@
 
         propagateThroughArgumentPositions();
 
+        processInvariants();
+
         m_pass = PrimaryPass;
         propagateToFixpoint();
         
@@ -55,7 +61,11 @@
         propagateToFixpoint();
         
         m_pass = DoubleVotingPass;
+        unsigned counter = 0;
         do {
+            if (verboseFixPointLoops)
+                ++counter;
+
             m_changed = false;
             doRoundOfDoubleVoting();
             if (!m_changed)
@@ -63,6 +73,9 @@
             m_changed = false;
             propagateForward();
         } while (m_changed);
+
+        if (verboseFixPointLoops)
+            dataLog("Iterated ", counter, " times in double voting fixpoint.\n");
         
         return true;
     }
@@ -70,9 +83,13 @@
 private:
     void propagateToFixpoint()
     {
+        unsigned counter = 0;
         do {
+            if (verboseFixPointLoops)
+                ++counter;
+
             m_changed = false;
-            
+
             // Forward propagation is near-optimal for both topologically-sorted and
             // DFS-sorted code.
             propagateForward();
@@ -86,6 +103,9 @@
             m_changed = false;
             propagateBackward();
         } while (m_changed);
+
+        if (verboseFixPointLoops)
+            dataLog("Iterated ", counter, " times in propagateToFixpoint.\n");
     }
     
     bool setPrediction(SpeculatedType prediction)
@@ -132,19 +152,6 @@
         bool changed = false;
         
         switch (op) {
-        case JSConstant: {
-            SpeculatedType type = speculationFromValue(node->asJSValue());
-            if (type == SpecInt52AsDouble && enableInt52())
-                type = SpecInt52;
-            changed |= setPrediction(type);
-            break;
-        }
-        case DoubleConstant: {
-            SpeculatedType type = speculationFromValue(node->asJSValue());
-            changed |= setPrediction(type);
-            break;
-        }
-            
         case GetLocal: {
             VariableAccessData* variable = node->variableAccessData();
             SpeculatedType prediction = variable->prediction();
@@ -160,92 +167,7 @@
             changed |= variableAccessData->predict(node->child1()->prediction());
             break;
         }
-            
-        case BitAnd:
-        case BitOr:
-        case BitXor:
-        case BitRShift:
-        case BitLShift:
-        case BitURShift:
-        case ArithIMul:
-        case ArithClz32: {
-            changed |= setPrediction(SpecInt32);
-            break;
-        }
 
-        case TryGetById: {
-            changed |= setPrediction(SpecBytecodeTop);
-            break;
-        }
-
-        case ArrayPop:
-        case ArrayPush:
-        case RegExpExec:
-        case RegExpTest:
-        case StringReplace:
-        case GetById:
-        case GetByIdFlush:
-        case GetByOffset:
-        case MultiGetByOffset:
-        case GetDirectPname:
-        case Call:
-        case TailCallInlinedCaller:
-        case Construct:
-        case CallVarargs:
-        case TailCallVarargsInlinedCaller:
-        case ConstructVarargs:
-        case CallForwardVarargs:
-        case ConstructForwardVarargs:
-        case TailCallForwardVarargsInlinedCaller:
-        case GetGlobalVar:
-        case GetGlobalLexicalVariable:
-        case GetClosureVar:
-        case GetFromArguments: {
-            changed |= setPrediction(node->getHeapPrediction());
-            break;
-        }
-
-        case GetDynamicVar: {
-            changed |= setPrediction(SpecBytecodeTop);
-            break;
-        }
-            
-        case GetGetterSetterByOffset:
-        case GetExecutable: {
-            changed |= setPrediction(SpecCellOther);
-            break;
-        }
-
-        case GetGetter:
-        case GetSetter:
-        case GetCallee:
-        case NewFunction:
-        case NewGeneratorFunction: {
-            changed |= setPrediction(SpecFunction);
-            break;
-        }
-            
-        case GetArgumentCount: {
-            changed |= setPrediction(SpecInt32);
-            break;
-        }
-
-        case GetRestLength: {
-            changed |= setPrediction(SpecInt32);
-            break;
-        }
-
-        case GetTypedArrayByteOffset:
-        case GetArrayLength: {
-            changed |= setPrediction(SpecInt32);
-            break;
-        }
-
-        case StringCharCodeAt: {
-            changed |= setPrediction(SpecInt32);
-            break;
-        }
-
         case UInt32ToNumber: {
             if (node->canSpeculateInt32(m_pass))
                 changed |= mergePrediction(SpecInt32);
@@ -381,21 +303,6 @@
             break;
         }
 
-        case ArithPow:
-        case ArithSqrt:
-        case ArithFRound:
-        case ArithSin:
-        case ArithCos:
-        case ArithLog: {
-            changed |= setPrediction(SpecBytecodeDouble);
-            break;
-        }
-
-        case ArithRandom: {
-            changed |= setPrediction(SpecDoubleReal);
-            break;
-        }
-
         case ArithRound:
         case ArithFloor:
         case ArithCeil:
@@ -417,37 +324,6 @@
             break;
         }
 
-        case DeleteById:
-        case LogicalNot:
-        case CompareLess:
-        case CompareLessEq:
-        case CompareGreater:
-        case CompareGreaterEq:
-        case CompareEq:
-        case CompareStrictEq:
-        case OverridesHasInstance:
-        case InstanceOf:
-        case InstanceOfCustom:
-        case IsArrayObject:
-        case IsJSArray:
-        case IsArrayConstructor:
-        case IsUndefined:
-        case IsBoolean:
-        case IsNumber:
-        case IsString:
-        case IsObject:
-        case IsObjectOrNull:
-        case IsFunction:
-        case IsRegExpObject: {
-            changed |= setPrediction(SpecBoolean);
-            break;
-        }
-
-        case TypeOf: {
-            changed |= setPrediction(SpecStringIdent);
-            break;
-        }
-
         case GetByVal: {
             if (!node->child1()->prediction())
                 break;
@@ -496,20 +372,7 @@
             }
             break;
         }
-            
-        case GetButterfly:
-        case GetIndexedPropertyStorage:
-        case AllocatePropertyStorage:
-        case ReallocatePropertyStorage: {
-            changed |= setPrediction(SpecOther);
-            break;
-        }
 
-        case CallObjectConstructor: {
-            changed |= setPrediction(SpecObject);
-            break;
-        }
-
         case ToThis: {
             // ToThis in methods for primitive types should speculate primitive types in strict mode.
             ECMAMode ecmaMode = m_graph.executableFor(node->origin.semantic)->isStrictMode() ? StrictMode : NotStrictMode;
@@ -569,48 +432,408 @@
             break;
         }
             
+        case ToPrimitive: {
+            SpeculatedType child = node->child1()->prediction();
+            if (child)
+                changed |= mergePrediction(resultOfToPrimitive(child));
+            break;
+        }
+
+        default:
+            break;
+        }
+
+        m_changed |= changed;
+    }
+        
+    void propagateForward()
+    {
+        for (Node* node : m_dependentNodes) {
+            m_currentNode = node;
+            propagate(m_currentNode);
+        }
+    }
+
+    void propagateBackward()
+    {
+        for (unsigned i = m_dependentNodes.size(); i--;) {
+            m_currentNode = m_dependentNodes[i];
+            propagate(m_currentNode);
+        }
+    }
+    
+    void doDoubleVoting(Node* node, float weight)
+    {
+        // Loop pre-headers created by OSR entrypoint creation may have NaN weight to indicate
+        // that we actually don't know they weight. Assume that they execute once. This turns
+        // out to be an OK assumption since the pre-header doesn't have any meaningful code.
+        if (weight != weight)
+            weight = 1;
+        
+        switch (node->op()) {
+        case ValueAdd:
+        case ArithAdd:
+        case ArithSub: {
+            SpeculatedType left = node->child1()->prediction();
+            SpeculatedType right = node->child2()->prediction();
+                
+            DoubleBallot ballot;
+                
+            if (isFullNumberSpeculation(left)
+                && isFullNumberSpeculation(right)
+                && !m_graph.addShouldSpeculateInt32(node, m_pass)
+                && !m_graph.addShouldSpeculateMachineInt(node))
+                ballot = VoteDouble;
+            else
+                ballot = VoteValue;
+                
+            m_graph.voteNode(node->child1(), ballot, weight);
+            m_graph.voteNode(node->child2(), ballot, weight);
+            break;
+        }
+
+        case ArithMul: {
+            SpeculatedType left = node->child1()->prediction();
+            SpeculatedType right = node->child2()->prediction();
+                
+            DoubleBallot ballot;
+                
+            if (isFullNumberSpeculation(left)
+                && isFullNumberSpeculation(right)
+                && !m_graph.binaryArithShouldSpeculateInt32(node, m_pass)
+                && !m_graph.binaryArithShouldSpeculateMachineInt(node, m_pass))
+                ballot = VoteDouble;
+            else
+                ballot = VoteValue;
+                
+            m_graph.voteNode(node->child1(), ballot, weight);
+            m_graph.voteNode(node->child2(), ballot, weight);
+            break;
+        }
+
+        case ArithMin:
+        case ArithMax:
+        case ArithMod:
+        case ArithDiv: {
+            SpeculatedType left = node->child1()->prediction();
+            SpeculatedType right = node->child2()->prediction();
+                
+            DoubleBallot ballot;
+                
+            if (isFullNumberSpeculation(left)
+                && isFullNumberSpeculation(right)
+                && !m_graph.binaryArithShouldSpeculateInt32(node, m_pass))
+                ballot = VoteDouble;
+            else
+                ballot = VoteValue;
+                
+            m_graph.voteNode(node->child1(), ballot, weight);
+            m_graph.voteNode(node->child2(), ballot, weight);
+            break;
+        }
+
+        case ArithAbs:
+            DoubleBallot ballot;
+            if (node->child1()->shouldSpeculateNumber()
+                && !m_graph.unaryArithShouldSpeculateInt32(node, m_pass))
+                ballot = VoteDouble;
+            else
+                ballot = VoteValue;
+                
+            m_graph.voteNode(node->child1(), ballot, weight);
+            break;
+                
+        case ArithSqrt:
+        case ArithCos:
+        case ArithSin:
+        case ArithLog:
+            if (node->child1()->shouldSpeculateNumber())
+                m_graph.voteNode(node->child1(), VoteDouble, weight);
+            else
+                m_graph.voteNode(node->child1(), VoteValue, weight);
+            break;
+                
+        case SetLocal: {
+            SpeculatedType prediction = node->child1()->prediction();
+            if (isDoubleSpeculation(prediction))
+                node->variableAccessData()->vote(VoteDouble, weight);
+            else if (!isFullNumberSpeculation(prediction)
+                || isInt32Speculation(prediction) || isMachineIntSpeculation(prediction))
+                node->variableAccessData()->vote(VoteValue, weight);
+            break;
+        }
+
+        case PutByValDirect:
+        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, weight);
+            m_graph.voteNode(child2, VoteValue, weight);
+            switch (node->arrayMode().type()) {
+            case Array::Double:
+                m_graph.voteNode(child3, VoteDouble, weight);
+                break;
+            default:
+                m_graph.voteNode(child3, VoteValue, weight);
+                break;
+            }
+            break;
+        }
+            
+        case MovHint:
+            // Ignore these since they have no effect on in-DFG execution.
+            break;
+            
+        default:
+            m_graph.voteChildren(node, VoteValue, weight);
+            break;
+        }
+    }
+    
+    void doRoundOfDoubleVoting()
+    {
+        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.numBlocks(); ++blockIndex) {
+            BasicBlock* block = m_graph.block(blockIndex);
+            if (!block)
+                continue;
+            ASSERT(block->isReachable);
+            for (unsigned i = 0; i < block->size(); ++i) {
+                m_currentNode = block->at(i);
+                doDoubleVoting(m_currentNode, block->executionCount);
+            }
+        }
+        for (unsigned i = 0; i < m_graph.m_variableAccessData.size(); ++i) {
+            VariableAccessData* variableAccessData = &m_graph.m_variableAccessData[i];
+            if (!variableAccessData->isRoot())
+                continue;
+            m_changed |= variableAccessData->tallyVotesForShouldUseDoubleFormat();
+        }
+        propagateThroughArgumentPositions();
+        for (unsigned i = 0; i < m_graph.m_variableAccessData.size(); ++i) {
+            VariableAccessData* variableAccessData = &m_graph.m_variableAccessData[i];
+            if (!variableAccessData->isRoot())
+                continue;
+            m_changed |= variableAccessData->makePredictionForDoubleFormat();
+        }
+    }
+    
+    void propagateThroughArgumentPositions()
+    {
+        for (unsigned i = 0; i < m_graph.m_argumentPositions.size(); ++i)
+            m_changed |= m_graph.m_argumentPositions[i].mergeArgumentPredictionAwareness();
+    }
+
+    // Sets any predictions that do not depends on other nodes.
+    void processInvariants()
+    {
+        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
+            for (Node* node : *block) {
+                m_currentNode = node;
+                processInvariantsForNode();
+            }
+        }
+    }
+
+    void processInvariantsForNode()
+    {
+        switch (m_currentNode->op()) {
+        case JSConstant: {
+            SpeculatedType type = speculationFromValue(m_currentNode->asJSValue());
+            if (type == SpecInt52AsDouble && enableInt52())
+                type = SpecInt52;
+            setPrediction(type);
+            break;
+        }
+        case DoubleConstant: {
+            SpeculatedType type = speculationFromValue(m_currentNode->asJSValue());
+            setPrediction(type);
+            break;
+        }
+        case BitAnd:
+        case BitOr:
+        case BitXor:
+        case BitRShift:
+        case BitLShift:
+        case BitURShift:
+        case ArithIMul:
+        case ArithClz32: {
+            setPrediction(SpecInt32);
+            break;
+        }
+
+        case TryGetById: {
+            setPrediction(SpecBytecodeTop);
+            break;
+        }
+        case ArrayPop:
+        case ArrayPush:
+        case RegExpExec:
+        case RegExpTest:
+        case StringReplace:
+        case GetById:
+        case GetByIdFlush:
+        case GetByOffset:
+        case MultiGetByOffset:
+        case GetDirectPname:
+        case Call:
+        case TailCallInlinedCaller:
+        case Construct:
+        case CallVarargs:
+        case TailCallVarargsInlinedCaller:
+        case ConstructVarargs:
+        case CallForwardVarargs:
+        case ConstructForwardVarargs:
+        case TailCallForwardVarargsInlinedCaller:
+        case GetGlobalVar:
+        case GetGlobalLexicalVariable:
+        case GetClosureVar:
+        case GetFromArguments: {
+            setPrediction(m_currentNode->getHeapPrediction());
+            break;
+        }
+
+        case GetDynamicVar: {
+            setPrediction(SpecBytecodeTop);
+            break;
+        }
+            
+        case GetGetterSetterByOffset:
+        case GetExecutable: {
+            setPrediction(SpecCellOther);
+            break;
+        }
+
+        case GetGetter:
+        case GetSetter:
+        case GetCallee:
+        case NewFunction:
+        case NewGeneratorFunction: {
+            setPrediction(SpecFunction);
+            break;
+        }
+            
+        case GetArgumentCount: {
+            setPrediction(SpecInt32);
+            break;
+        }
+
+        case GetRestLength: {
+            setPrediction(SpecInt32);
+            break;
+        }
+
+        case GetTypedArrayByteOffset:
+        case GetArrayLength: {
+            setPrediction(SpecInt32);
+            break;
+        }
+
+        case StringCharCodeAt: {
+            setPrediction(SpecInt32);
+            break;
+        }
+        case ArithPow:
+        case ArithSqrt:
+        case ArithFRound:
+        case ArithSin:
+        case ArithCos:
+        case ArithLog: {
+            setPrediction(SpecBytecodeDouble);
+            break;
+        }
+
+        case ArithRandom: {
+            setPrediction(SpecDoubleReal);
+            break;
+        }
+        case DeleteById:
+        case LogicalNot:
+        case CompareLess:
+        case CompareLessEq:
+        case CompareGreater:
+        case CompareGreaterEq:
+        case CompareEq:
+        case CompareStrictEq:
+        case OverridesHasInstance:
+        case InstanceOf:
+        case InstanceOfCustom:
+        case IsArrayObject:
+        case IsJSArray:
+        case IsArrayConstructor:
+        case IsUndefined:
+        case IsBoolean:
+        case IsNumber:
+        case IsString:
+        case IsObject:
+        case IsObjectOrNull:
+        case IsFunction:
+        case IsRegExpObject: {
+            setPrediction(SpecBoolean);
+            break;
+        }
+
+        case TypeOf: {
+            setPrediction(SpecStringIdent);
+            break;
+        }
+        case GetButterfly:
+        case GetIndexedPropertyStorage:
+        case AllocatePropertyStorage:
+        case ReallocatePropertyStorage: {
+            setPrediction(SpecOther);
+            break;
+        }
+
+        case CallObjectConstructor: {
+            setPrediction(SpecObject);
+            break;
+        }
         case SkipScope:
         case GetGlobalObject: {
-            changed |= setPrediction(SpecObjectOther);
+            setPrediction(SpecObjectOther);
             break;
         }
 
         case ResolveScope: {
-            changed |= setPrediction(SpecObjectOther);
+            setPrediction(SpecObjectOther);
             break;
         }
             
         case CreateThis:
         case NewObject: {
-            changed |= setPrediction(SpecFinalObject);
+            setPrediction(SpecFinalObject);
             break;
         }
             
         case NewArray:
         case NewArrayWithSize:
         case NewArrayBuffer: {
-            changed |= setPrediction(SpecArray);
+            setPrediction(SpecArray);
             break;
         }
             
         case NewTypedArray: {
-            changed |= setPrediction(speculationFromTypedArrayType(node->typedArrayType()));
+            setPrediction(speculationFromTypedArrayType(m_currentNode->typedArrayType()));
             break;
         }
             
         case NewRegexp: {
-            changed |= setPrediction(SpecRegExpObject);
+            setPrediction(SpecRegExpObject);
             break;
         }
             
         case CreateActivation: {
-            changed |= setPrediction(SpecObjectOther);
+            setPrediction(SpecObjectOther);
             break;
         }
         
         case StringFromCharCode: {
-            changed |= setPrediction(SpecString);
-            changed |= node->child1()->mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsInt);            
+            setPrediction(SpecString);
+            m_currentNode->child1()->mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsInt);
             break;
         }
         case StringCharAt:
@@ -618,43 +841,94 @@
         case ToString:
         case MakeRope:
         case StrCat: {
-            changed |= setPrediction(SpecString);
+            setPrediction(SpecString);
             break;
         }
-            
-        case ToPrimitive: {
-            SpeculatedType child = node->child1()->prediction();
-            if (child)
-                changed |= mergePrediction(resultOfToPrimitive(child));
-            break;
-        }
-            
         case NewStringObject: {
-            changed |= setPrediction(SpecStringObject);
+            setPrediction(SpecStringObject);
             break;
         }
             
         case CreateDirectArguments: {
-            changed |= setPrediction(SpecDirectArguments);
+            setPrediction(SpecDirectArguments);
             break;
         }
             
         case CreateScopedArguments: {
-            changed |= setPrediction(SpecScopedArguments);
+            setPrediction(SpecScopedArguments);
             break;
         }
             
         case CreateClonedArguments: {
-            changed |= setPrediction(SpecObjectOther);
+            setPrediction(SpecObjectOther);
             break;
         }
             
         case FiatInt52: {
             RELEASE_ASSERT(enableInt52());
-            changed |= setPrediction(SpecMachineInt);
+            setPrediction(SpecMachineInt);
             break;
         }
 
+        case GetScope:
+            setPrediction(SpecObjectOther);
+            break;
+
+        case In:
+            setPrediction(SpecBoolean);
+            break;
+
+        case GetEnumerableLength: {
+            setPrediction(SpecInt32);
+            break;
+        }
+        case HasGenericProperty:
+        case HasStructureProperty:
+        case HasIndexedProperty: {
+            setPrediction(SpecBoolean);
+            break;
+        }
+        case GetPropertyEnumerator: {
+            setPrediction(SpecCell);
+            break;
+        }
+        case GetEnumeratorStructurePname: {
+            setPrediction(SpecCell | SpecOther);
+            break;
+        }
+        case GetEnumeratorGenericPname: {
+            setPrediction(SpecCell | SpecOther);
+            break;
+        }
+        case ToIndexString: {
+            setPrediction(SpecString);
+            break;
+        }
+
+        case GetLocal:
+        case SetLocal:
+        case UInt32ToNumber:
+        case ValueAdd:
+        case ArithAdd:
+        case ArithSub:
+        case ArithNegate:
+        case ArithMin:
+        case ArithMax:
+        case ArithMul:
+        case ArithDiv:
+        case ArithMod:
+        case ArithRound:
+        case ArithFloor:
+        case ArithCeil:
+        case ArithTrunc:
+        case ArithAbs:
+        case GetByVal:
+        case ToThis:
+        case ToPrimitive: {
+            m_dependentNodes.append(m_currentNode);
+            break;
+        }
+
         case PutByValAlias:
         case DoubleAsInt32:
         case GetLocalUnlinked:
@@ -696,7 +970,7 @@
         case LazyJSConstant: {
             // This node should never be visible at this stage of compilation. It is
             // inserted by fixup(), which follows this phase.
-            DFG_CRASH(m_graph, node, "Unexpected node during prediction propagation");
+            DFG_CRASH(m_graph, m_currentNode, "Unexpected node during prediction propagation");
             break;
         }
         
@@ -710,42 +984,7 @@
             // These don't get inserted until we go into SSA.
             RELEASE_ASSERT_NOT_REACHED();
             break;
-    
-        case GetScope:
-            changed |= setPrediction(SpecObjectOther);
-            break;
 
-        case In:
-            changed |= setPrediction(SpecBoolean);
-            break;
-
-        case GetEnumerableLength: {
-            changed |= setPrediction(SpecInt32);
-            break;
-        }
-        case HasGenericProperty:
-        case HasStructureProperty:
-        case HasIndexedProperty: {
-            changed |= setPrediction(SpecBoolean);
-            break;
-        }
-        case GetPropertyEnumerator: {
-            changed |= setPrediction(SpecCell);
-            break;
-        }
-        case GetEnumeratorStructurePname: {
-            changed |= setPrediction(SpecCell | SpecOther);
-            break;
-        }
-        case GetEnumeratorGenericPname: {
-            changed |= setPrediction(SpecCell | SpecOther);
-            break;
-        }
-        case ToIndexString: {
-            changed |= setPrediction(SpecString);
-            break;
-        }
-
 #ifndef NDEBUG
         // These get ignored because they don't return anything.
         case PutByValDirect:
@@ -825,204 +1064,8 @@
             break;
 #endif
         }
-
-        m_changed |= changed;
     }
-        
-    void propagateForward()
-    {
-        for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
-            BasicBlock* block = m_graph.block(blockIndex);
-            if (!block)
-                continue;
-            ASSERT(block->isReachable);
-            for (unsigned i = 0; i < block->size(); ++i) {
-                m_currentNode = block->at(i);
-                propagate(m_currentNode);
-            }
-        }
-    }
-    
-    void propagateBackward()
-    {
-        for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
-            BasicBlock* block = m_graph.block(blockIndex);
-            if (!block)
-                continue;
-            ASSERT(block->isReachable);
-            for (unsigned i = block->size(); i--;) {
-                m_currentNode = block->at(i);
-                propagate(m_currentNode);
-            }
-        }
-    }
-    
-    void doDoubleVoting(Node* node, float weight)
-    {
-        // Loop pre-headers created by OSR entrypoint creation may have NaN weight to indicate
-        // that we actually don't know they weight. Assume that they execute once. This turns
-        // out to be an OK assumption since the pre-header doesn't have any meaningful code.
-        if (weight != weight)
-            weight = 1;
-        
-        switch (node->op()) {
-        case ValueAdd:
-        case ArithAdd:
-        case ArithSub: {
-            SpeculatedType left = node->child1()->prediction();
-            SpeculatedType right = node->child2()->prediction();
-                
-            DoubleBallot ballot;
-                
-            if (isFullNumberSpeculation(left)
-                && isFullNumberSpeculation(right)
-                && !m_graph.addShouldSpeculateInt32(node, m_pass)
-                && !m_graph.addShouldSpeculateMachineInt(node))
-                ballot = VoteDouble;
-            else
-                ballot = VoteValue;
-                
-            m_graph.voteNode(node->child1(), ballot, weight);
-            m_graph.voteNode(node->child2(), ballot, weight);
-            break;
-        }
-                
-        case ArithMul: {
-            SpeculatedType left = node->child1()->prediction();
-            SpeculatedType right = node->child2()->prediction();
-                
-            DoubleBallot ballot;
-                
-            if (isFullNumberSpeculation(left)
-                && isFullNumberSpeculation(right)
-                && !m_graph.binaryArithShouldSpeculateInt32(node, m_pass)
-                && !m_graph.binaryArithShouldSpeculateMachineInt(node, m_pass))
-                ballot = VoteDouble;
-            else
-                ballot = VoteValue;
-                
-            m_graph.voteNode(node->child1(), ballot, weight);
-            m_graph.voteNode(node->child2(), ballot, weight);
-            break;
-        }
 
-        case ArithMin:
-        case ArithMax:
-        case ArithMod:
-        case ArithDiv: {
-            SpeculatedType left = node->child1()->prediction();
-            SpeculatedType right = node->child2()->prediction();
-                
-            DoubleBallot ballot;
-                
-            if (isFullNumberSpeculation(left)
-                && isFullNumberSpeculation(right)
-                && !m_graph.binaryArithShouldSpeculateInt32(node, m_pass))
-                ballot = VoteDouble;
-            else
-                ballot = VoteValue;
-                
-            m_graph.voteNode(node->child1(), ballot, weight);
-            m_graph.voteNode(node->child2(), ballot, weight);
-            break;
-        }
-                
-        case ArithAbs:
-            DoubleBallot ballot;
-            if (node->child1()->shouldSpeculateNumber()
-                && !m_graph.unaryArithShouldSpeculateInt32(node, m_pass))
-                ballot = VoteDouble;
-            else
-                ballot = VoteValue;
-                
-            m_graph.voteNode(node->child1(), ballot, weight);
-            break;
-                
-        case ArithSqrt:
-        case ArithCos:
-        case ArithSin:
-        case ArithLog:
-            if (node->child1()->shouldSpeculateNumber())
-                m_graph.voteNode(node->child1(), VoteDouble, weight);
-            else
-                m_graph.voteNode(node->child1(), VoteValue, weight);
-            break;
-                
-        case SetLocal: {
-            SpeculatedType prediction = node->child1()->prediction();
-            if (isDoubleSpeculation(prediction))
-                node->variableAccessData()->vote(VoteDouble, weight);
-            else if (
-                !isFullNumberSpeculation(prediction)
-                || isInt32Speculation(prediction) || isMachineIntSpeculation(prediction))
-                node->variableAccessData()->vote(VoteValue, weight);
-            break;
-        }
-
-        case PutByValDirect:
-        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, weight);
-            m_graph.voteNode(child2, VoteValue, weight);
-            switch (node->arrayMode().type()) {
-            case Array::Double:
-                m_graph.voteNode(child3, VoteDouble, weight);
-                break;
-            default:
-                m_graph.voteNode(child3, VoteValue, weight);
-                break;
-            }
-            break;
-        }
-            
-        case MovHint:
-            // Ignore these since they have no effect on in-DFG execution.
-            break;
-            
-        default:
-            m_graph.voteChildren(node, VoteValue, weight);
-            break;
-        }
-    }
-    
-    void doRoundOfDoubleVoting()
-    {
-        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.numBlocks(); ++blockIndex) {
-            BasicBlock* block = m_graph.block(blockIndex);
-            if (!block)
-                continue;
-            ASSERT(block->isReachable);
-            for (unsigned i = 0; i < block->size(); ++i) {
-                m_currentNode = block->at(i);
-                doDoubleVoting(m_currentNode, block->executionCount);
-            }
-        }
-        for (unsigned i = 0; i < m_graph.m_variableAccessData.size(); ++i) {
-            VariableAccessData* variableAccessData = &m_graph.m_variableAccessData[i];
-            if (!variableAccessData->isRoot())
-                continue;
-            m_changed |= variableAccessData->tallyVotesForShouldUseDoubleFormat();
-        }
-        propagateThroughArgumentPositions();
-        for (unsigned i = 0; i < m_graph.m_variableAccessData.size(); ++i) {
-            VariableAccessData* variableAccessData = &m_graph.m_variableAccessData[i];
-            if (!variableAccessData->isRoot())
-                continue;
-            m_changed |= variableAccessData->makePredictionForDoubleFormat();
-        }
-    }
-    
-    void propagateThroughArgumentPositions()
-    {
-        for (unsigned i = 0; i < m_graph.m_argumentPositions.size(); ++i)
-            m_changed |= m_graph.m_argumentPositions[i].mergeArgumentPredictionAwareness();
-    }
-
     SpeculatedType resultOfToPrimitive(SpeculatedType type)
     {
         if (type & SpecObject) {
@@ -1036,11 +1079,14 @@
 
         return type;
     }
-    
+
+    Vector<Node*> m_dependentNodes;
     Node* m_currentNode;
     bool m_changed;
     PredictionPass m_pass; // We use different logic for considering predictions depending on how far along we are in propagation.
 };
+
+} // Anonymous namespace.
     
 bool performPredictionPropagation(Graph& graph)
 {
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to