Title: [189013] trunk/Source/_javascript_Core
Revision
189013
Author
[email protected]
Date
2015-08-27 00:16:07 -0700 (Thu, 27 Aug 2015)

Log Message

Node::origin should always be set, and the dead zone due to SSA Phis can just use exitOK=false
https://bugs.webkit.org/show_bug.cgi?id=148462

Reviewed by Saam Barati.

The need to label nodes that absolutely cannot exit was first observed when we introduced SSA form.
We indicated this by not setting the CodeOrigin.

But just recently (http://trac.webkit.org/changeset/188979), we added a more comprehensive "exitOK"
bit in NodeOrigin. After that change, there were two ways of indicating that you cannot exit:
!exitOK and an unset NodeOrigin. An unset NodeOrigin implied !exitOK.

Now, this change is about removing the old way so that we only use !exitOK. From now on, all nodes
must have their NodeOrigin set, and the IR validation will check this. This means that I could
remove various pieces of cruft for dealing with unset NodeOrigins, but I did have to add some new
cruft to ensure that all nodes we create have a NodeOrigin.

This change simplifies our IR by having a simpler rule about when NodeOrigin is set: it's always
set.

* dfg/DFGBasicBlock.cpp:
(JSC::DFG::BasicBlock::isInBlock):
(JSC::DFG::BasicBlock::removePredecessor):
(JSC::DFG::BasicBlock::firstOriginNode): Deleted.
(JSC::DFG::BasicBlock::firstOrigin): Deleted.
* dfg/DFGBasicBlock.h:
(JSC::DFG::BasicBlock::begin):
(JSC::DFG::BasicBlock::end):
(JSC::DFG::BasicBlock::numSuccessors):
(JSC::DFG::BasicBlock::successor):
* dfg/DFGCombinedLiveness.cpp:
(JSC::DFG::liveNodesAtHead):
* dfg/DFGConstantHoistingPhase.cpp:
* dfg/DFGCriticalEdgeBreakingPhase.cpp:
(JSC::DFG::CriticalEdgeBreakingPhase::breakCriticalEdge):
* dfg/DFGForAllKills.h:
(JSC::DFG::forAllKilledOperands):
* dfg/DFGIntegerRangeOptimizationPhase.cpp:
* dfg/DFGLoopPreHeaderCreationPhase.cpp:
(JSC::DFG::createPreHeader):
(JSC::DFG::LoopPreHeaderCreationPhase::run):
* dfg/DFGOSRAvailabilityAnalysisPhase.cpp:
(JSC::DFG::OSRAvailabilityAnalysisPhase::run):
* dfg/DFGObjectAllocationSinkingPhase.cpp:
* dfg/DFGPutStackSinkingPhase.cpp:
* dfg/DFGSSAConversionPhase.cpp:
(JSC::DFG::SSAConversionPhase::run):
* dfg/DFGValidate.cpp:
(JSC::DFG::Validate::validate):
(JSC::DFG::Validate::validateSSA):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (189012 => 189013)


--- trunk/Source/_javascript_Core/ChangeLog	2015-08-27 05:54:21 UTC (rev 189012)
+++ trunk/Source/_javascript_Core/ChangeLog	2015-08-27 07:16:07 UTC (rev 189013)
@@ -1,3 +1,56 @@
+2015-08-26  Filip Pizlo  <[email protected]>
+
+        Node::origin should always be set, and the dead zone due to SSA Phis can just use exitOK=false
+        https://bugs.webkit.org/show_bug.cgi?id=148462
+
+        Reviewed by Saam Barati.
+
+        The need to label nodes that absolutely cannot exit was first observed when we introduced SSA form.
+        We indicated this by not setting the CodeOrigin.
+
+        But just recently (http://trac.webkit.org/changeset/188979), we added a more comprehensive "exitOK"
+        bit in NodeOrigin. After that change, there were two ways of indicating that you cannot exit:
+        !exitOK and an unset NodeOrigin. An unset NodeOrigin implied !exitOK.
+
+        Now, this change is about removing the old way so that we only use !exitOK. From now on, all nodes
+        must have their NodeOrigin set, and the IR validation will check this. This means that I could
+        remove various pieces of cruft for dealing with unset NodeOrigins, but I did have to add some new
+        cruft to ensure that all nodes we create have a NodeOrigin.
+
+        This change simplifies our IR by having a simpler rule about when NodeOrigin is set: it's always
+        set.
+
+        * dfg/DFGBasicBlock.cpp:
+        (JSC::DFG::BasicBlock::isInBlock):
+        (JSC::DFG::BasicBlock::removePredecessor):
+        (JSC::DFG::BasicBlock::firstOriginNode): Deleted.
+        (JSC::DFG::BasicBlock::firstOrigin): Deleted.
+        * dfg/DFGBasicBlock.h:
+        (JSC::DFG::BasicBlock::begin):
+        (JSC::DFG::BasicBlock::end):
+        (JSC::DFG::BasicBlock::numSuccessors):
+        (JSC::DFG::BasicBlock::successor):
+        * dfg/DFGCombinedLiveness.cpp:
+        (JSC::DFG::liveNodesAtHead):
+        * dfg/DFGConstantHoistingPhase.cpp:
+        * dfg/DFGCriticalEdgeBreakingPhase.cpp:
+        (JSC::DFG::CriticalEdgeBreakingPhase::breakCriticalEdge):
+        * dfg/DFGForAllKills.h:
+        (JSC::DFG::forAllKilledOperands):
+        * dfg/DFGIntegerRangeOptimizationPhase.cpp:
+        * dfg/DFGLoopPreHeaderCreationPhase.cpp:
+        (JSC::DFG::createPreHeader):
+        (JSC::DFG::LoopPreHeaderCreationPhase::run):
+        * dfg/DFGOSRAvailabilityAnalysisPhase.cpp:
+        (JSC::DFG::OSRAvailabilityAnalysisPhase::run):
+        * dfg/DFGObjectAllocationSinkingPhase.cpp:
+        * dfg/DFGPutStackSinkingPhase.cpp:
+        * dfg/DFGSSAConversionPhase.cpp:
+        (JSC::DFG::SSAConversionPhase::run):
+        * dfg/DFGValidate.cpp:
+        (JSC::DFG::Validate::validate):
+        (JSC::DFG::Validate::validateSSA):
+
 2015-08-26  Saam barati  <[email protected]>
 
         MarkedBlock::allocateBlock will have the wrong allocation size when (sizeof(MarkedBlock) + bytes) is divisible by WTF::pageSize()

Modified: trunk/Source/_javascript_Core/dfg/DFGBasicBlock.cpp (189012 => 189013)


--- trunk/Source/_javascript_Core/dfg/DFGBasicBlock.cpp	2015-08-27 05:54:21 UTC (rev 189012)
+++ trunk/Source/_javascript_Core/dfg/DFGBasicBlock.cpp	2015-08-27 07:16:07 UTC (rev 189013)
@@ -102,21 +102,6 @@
     return false;
 }
 
-Node* BasicBlock::firstOriginNode()
-{
-    for (Node* node : *this) {
-        if (node->origin.isSet())
-            return node;
-    }
-    RELEASE_ASSERT_NOT_REACHED();
-    return nullptr;
-}
-
-NodeOrigin BasicBlock::firstOrigin()
-{
-    return firstOriginNode()->origin;
-}
-
 void BasicBlock::removePredecessor(BasicBlock* block)
 {
     for (unsigned i = 0; i < predecessors.size(); ++i) {

Modified: trunk/Source/_javascript_Core/dfg/DFGBasicBlock.h (189012 => 189013)


--- trunk/Source/_javascript_Core/dfg/DFGBasicBlock.h	2015-08-27 05:54:21 UTC (rev 189012)
+++ trunk/Source/_javascript_Core/dfg/DFGBasicBlock.h	2015-08-27 07:16:07 UTC (rev 189013)
@@ -141,10 +141,7 @@
     
     BlockNodeList::iterator begin() { return m_nodes.begin(); }
     BlockNodeList::iterator end() { return m_nodes.end(); }
-    
-    Node* firstOriginNode();
-    NodeOrigin firstOrigin();
-    
+
     unsigned numSuccessors() { return terminal()->numSuccessors(); }
     
     BasicBlock*& successor(unsigned index)

Modified: trunk/Source/_javascript_Core/dfg/DFGCombinedLiveness.cpp (189012 => 189013)


--- trunk/Source/_javascript_Core/dfg/DFGCombinedLiveness.cpp	2015-08-27 05:54:21 UTC (rev 189012)
+++ trunk/Source/_javascript_Core/dfg/DFGCombinedLiveness.cpp	2015-08-27 07:16:07 UTC (rev 189013)
@@ -43,7 +43,7 @@
     
     AvailabilityMap& availabilityMap = block->ssa->availabilityAtHead;
     graph.forAllLocalsLiveInBytecode(
-        block->firstOrigin().forExit,
+        block->at(0)->origin.forExit,
         [&] (VirtualRegister reg) {
             availabilityMap.closeStartingWithLocal(
                 reg,

Modified: trunk/Source/_javascript_Core/dfg/DFGConstantHoistingPhase.cpp (189012 => 189013)


--- trunk/Source/_javascript_Core/dfg/DFGConstantHoistingPhase.cpp	2015-08-27 05:54:21 UTC (rev 189012)
+++ trunk/Source/_javascript_Core/dfg/DFGConstantHoistingPhase.cpp	2015-08-27 07:16:07 UTC (rev 189013)
@@ -94,7 +94,7 @@
                     HashMap<FrozenValue*, Node*>& values = valuesFor(node->op());
                     auto result = values.add(node->constant(), node);
                     if (result.isNewEntry)
-                        node->origin = NodeOrigin();
+                        node->origin = m_graph.block(0)->at(0)->origin;
                     else {
                         node->setReplacement(result.iterator->value);
                         toFree.append(node);

Modified: trunk/Source/_javascript_Core/dfg/DFGCriticalEdgeBreakingPhase.cpp (189012 => 189013)


--- trunk/Source/_javascript_Core/dfg/DFGCriticalEdgeBreakingPhase.cpp	2015-08-27 05:54:21 UTC (rev 189012)
+++ trunk/Source/_javascript_Core/dfg/DFGCriticalEdgeBreakingPhase.cpp	2015-08-27 07:16:07 UTC (rev 189013)
@@ -77,7 +77,7 @@
         // don't know its execution frequency.
         BasicBlock* pad = m_insertionSet.insertBefore(*successor, PNaN);
         pad->appendNode(
-            m_graph, SpecNone, Jump, (*successor)->firstOrigin(), OpInfo(*successor));
+            m_graph, SpecNone, Jump, (*successor)->at(0)->origin, OpInfo(*successor));
         pad->predecessors.append(predecessor);
         (*successor)->replacePredecessor(predecessor, pad);
         

Modified: trunk/Source/_javascript_Core/dfg/DFGForAllKills.h (189012 => 189013)


--- trunk/Source/_javascript_Core/dfg/DFGForAllKills.h	2015-08-27 05:54:21 UTC (rev 189012)
+++ trunk/Source/_javascript_Core/dfg/DFGForAllKills.h	2015-08-27 07:16:07 UTC (rev 189013)
@@ -55,33 +55,18 @@
     CodeOrigin after = nodeAfter->origin.forExit;
     
     VirtualRegister alreadyNoted;
-    if (!!after) {
-        // If we MovHint something that is live at the time, then we kill the old value.
-        if (nodeAfter->containsMovHint()) {
-            VirtualRegister reg = nodeAfter->unlinkedLocal();
-            if (graph.isLiveInBytecode(reg, after)) {
-                functor(reg);
-                alreadyNoted = reg;
-            }
+    // If we MovHint something that is live at the time, then we kill the old value.
+    if (nodeAfter->containsMovHint()) {
+        VirtualRegister reg = nodeAfter->unlinkedLocal();
+        if (graph.isLiveInBytecode(reg, after)) {
+            functor(reg);
+            alreadyNoted = reg;
         }
     }
     
-    if (!before) {
-        if (!after)
-            return;
-        // The true before-origin is the origin at predecessors that jump to us. But there can be
-        // many such predecessors and they will likely all have a different origin. So, it's better
-        // to do the conservative thing.
-        graph.forAllLocalsLiveInBytecode(after, functor);
-        return;
-    }
-    
     if (before == after)
         return;
     
-    // before could be unset even if after is, but the opposite cannot happen.
-    ASSERT(!!after);
-    
     // It's easier to do this if the inline call frames are the same. This is way faster than the
     // other loop, below.
     if (before.inlineCallFrame == after.inlineCallFrame) {

Modified: trunk/Source/_javascript_Core/dfg/DFGIntegerRangeOptimizationPhase.cpp (189012 => 189013)


--- trunk/Source/_javascript_Core/dfg/DFGIntegerRangeOptimizationPhase.cpp	2015-08-27 05:54:21 UTC (rev 189012)
+++ trunk/Source/_javascript_Core/dfg/DFGIntegerRangeOptimizationPhase.cpp	2015-08-27 07:16:07 UTC (rev 189013)
@@ -999,7 +999,7 @@
             }
         }
         if (!m_zero) {
-            m_zero = m_insertionSet.insertConstant(0, NodeOrigin(), jsNumber(0));
+            m_zero = m_insertionSet.insertConstant(0, m_graph.block(0)->at(0)->origin, jsNumber(0));
             m_insertionSet.execute(m_graph.block(0));
         }
         

Modified: trunk/Source/_javascript_Core/dfg/DFGLoopPreHeaderCreationPhase.cpp (189012 => 189013)


--- trunk/Source/_javascript_Core/dfg/DFGLoopPreHeaderCreationPhase.cpp	2015-08-27 05:54:21 UTC (rev 189012)
+++ trunk/Source/_javascript_Core/dfg/DFGLoopPreHeaderCreationPhase.cpp	2015-08-27 07:16:07 UTC (rev 189013)
@@ -42,7 +42,7 @@
     // Don't bother to preserve execution frequencies for now.
     BasicBlock* preHeader = insertionSet.insertBefore(block, PNaN);
     preHeader->appendNode(
-        graph, SpecNone, Jump, block->firstOrigin(), OpInfo(block));
+        graph, SpecNone, Jump, block->at(0)->origin, OpInfo(block));
     
     for (unsigned predecessorIndex = 0; predecessorIndex < block->predecessors.size(); predecessorIndex++) {
         BasicBlock* predecessor = block->predecessors[predecessorIndex];
@@ -108,7 +108,7 @@
             // A pre-header is most useful if it's possible to exit from its terminal. Hence
             // if the terminal of the existing pre-header doesn't allow for exit, but the first
             // origin of the loop header does, then we should create a new pre-header.
-            if (!needsNewPreHeader && loop.header()->firstOrigin().exitOK
+            if (!needsNewPreHeader && loop.header()->at(0)->origin.exitOK
                 && !existingPreHeader->terminal()->origin.exitOK)
                 needsNewPreHeader = true;
             

Modified: trunk/Source/_javascript_Core/dfg/DFGOSRAvailabilityAnalysisPhase.cpp (189012 => 189013)


--- trunk/Source/_javascript_Core/dfg/DFGOSRAvailabilityAnalysisPhase.cpp	2015-08-27 05:54:21 UTC (rev 189012)
+++ trunk/Source/_javascript_Core/dfg/DFGOSRAvailabilityAnalysisPhase.cpp	2015-08-27 07:16:07 UTC (rev 189013)
@@ -91,7 +91,7 @@
                     BasicBlock* successor = block->successor(successorIndex);
                     successor->ssa->availabilityAtHead.merge(calculator.m_availability);
                     successor->ssa->availabilityAtHead.pruneByLiveness(
-                        m_graph, successor->firstOrigin().forExit);
+                        m_graph, successor->at(0)->origin.forExit);
                 }
             }
         } while (changed);

Modified: trunk/Source/_javascript_Core/dfg/DFGObjectAllocationSinkingPhase.cpp (189012 => 189013)


--- trunk/Source/_javascript_Core/dfg/DFGObjectAllocationSinkingPhase.cpp	2015-08-27 05:54:21 UTC (rev 189012)
+++ trunk/Source/_javascript_Core/dfg/DFGObjectAllocationSinkingPhase.cpp	2015-08-27 07:16:07 UTC (rev 189013)
@@ -1548,7 +1548,7 @@
         // with useless constants everywhere
         HashMap<FrozenValue*, Node*> lazyMapping;
         if (!m_bottom)
-            m_bottom = m_insertionSet.insertConstant(0, NodeOrigin(), jsNumber(1927));
+            m_bottom = m_insertionSet.insertConstant(0, m_graph.block(0)->at(0)->origin, jsNumber(1927));
         for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
             m_heap = m_heapAtHead[block];
 
@@ -1621,7 +1621,7 @@
                 if (m_heapAtHead[block].follow(location))
                     return nullptr;
 
-                Node* phiNode = m_graph.addNode(SpecHeapTop, Phi, NodeOrigin());
+                Node* phiNode = m_graph.addNode(SpecHeapTop, Phi, block->at(0)->origin.withInvalidExit());
                 phiNode->mergeFlags(NodeResultJS);
                 return phiNode;
             });
@@ -1638,7 +1638,7 @@
                 if (!m_heapAtHead[block].getAllocation(identifier).isEscapedAllocation())
                     return nullptr;
 
-                Node* phiNode = m_graph.addNode(SpecHeapTop, Phi, NodeOrigin());
+                Node* phiNode = m_graph.addNode(SpecHeapTop, Phi, block->at(0)->origin.withInvalidExit());
                 phiNode->mergeFlags(NodeResultJS);
                 return phiNode;
             });
@@ -1669,7 +1669,9 @@
 
                 if (m_sinkCandidates.contains(location.base())) {
                     m_insertionSet.insert(
-                        0, location.createHint(m_graph, NodeOrigin(), phiDef->value()));
+                        0,
+                        location.createHint(
+                            m_graph, block->at(0)->origin.withInvalidExit(), phiDef->value()));
                 }
             }
 
@@ -1680,7 +1682,9 @@
                 Node* identifier = indexToNode[variable->index()];
                 m_escapeeToMaterialization.add(identifier, phiDef->value());
                 bool canExit = false;
-                insertOSRHintsForUpdate(0, NodeOrigin(), canExit, availabilityCalculator.m_availability, identifier, phiDef->value());
+                insertOSRHintsForUpdate(
+                    0, block->at(0)->origin, canExit,
+                    availabilityCalculator.m_availability, identifier, phiDef->value());
             }
 
             if (verbose) {

Modified: trunk/Source/_javascript_Core/dfg/DFGPutStackSinkingPhase.cpp (189012 => 189013)


--- trunk/Source/_javascript_Core/dfg/DFGPutStackSinkingPhase.cpp	2015-08-27 05:54:21 UTC (rev 189012)
+++ trunk/Source/_javascript_Core/dfg/DFGPutStackSinkingPhase.cpp	2015-08-27 07:16:07 UTC (rev 189013)
@@ -358,7 +358,7 @@
                 if (verbose)
                     dataLog("Adding Phi for ", operand, " at ", pointerDump(block), "\n");
                 
-                Node* phiNode = m_graph.addNode(SpecHeapTop, Phi, NodeOrigin());
+                Node* phiNode = m_graph.addNode(SpecHeapTop, Phi, block->at(0)->origin.withInvalidExit());
                 phiNode->mergeFlags(resultFor(format));
                 return phiNode;
             });

Modified: trunk/Source/_javascript_Core/dfg/DFGSSAConversionPhase.cpp (189012 => 189013)


--- trunk/Source/_javascript_Core/dfg/DFGSSAConversionPhase.cpp	2015-08-27 05:54:21 UTC (rev 189012)
+++ trunk/Source/_javascript_Core/dfg/DFGSSAConversionPhase.cpp	2015-08-27 07:16:07 UTC (rev 189013)
@@ -149,7 +149,7 @@
                     return nullptr;
                 
                 Node* phiNode = m_graph.addNode(
-                    variable->prediction(), Phi, NodeOrigin());
+                    variable->prediction(), Phi, block->at(0)->origin.withInvalidExit());
                 FlushFormat format = variable->flushFormat();
                 NodeFlags result = resultFor(format);
                 phiNode->mergeFlags(result);
@@ -252,9 +252,12 @@
                 valueForOperand.operand(variable->local()) = phiDef->value();
                 
                 m_insertionSet.insertNode(
-                    phiInsertionPoint, SpecNone, MovHint, NodeOrigin(),
+                    phiInsertionPoint, SpecNone, MovHint, block->at(0)->origin.withInvalidExit(),
                     OpInfo(variable->local().offset()), phiDef->value()->defaultEdge());
             }
+
+            if (block->at(0)->origin.exitOK)
+                m_insertionSet.insertNode(phiInsertionPoint, SpecNone, ExitOK, block->at(0)->origin);
             
             for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
                 Node* node = block->at(nodeIndex);

Modified: trunk/Source/_javascript_Core/dfg/DFGValidate.cpp (189012 => 189013)


--- trunk/Source/_javascript_Core/dfg/DFGValidate.cpp	2015-08-27 05:54:21 UTC (rev 189012)
+++ trunk/Source/_javascript_Core/dfg/DFGValidate.cpp	2015-08-27 07:16:07 UTC (rev 189013)
@@ -187,6 +187,7 @@
             for (size_t i = 0; i < block->size(); ++i) {
                 Node* node = block->at(i);
 
+                VALIDATE((node), node->origin.isSet());
                 VALIDATE((node), node->origin.semantic.isSet() == node->origin.forExit.isSet());
                 VALIDATE((node), !(!node->origin.forExit.isSet() && node->origin.exitOK));
                 VALIDATE((node), !(mayExit(m_graph, node) == Exits && !node->origin.exitOK));
@@ -526,20 +527,21 @@
                 continue;
             
             VALIDATE((block), block->phis.isEmpty());
+
+            bool didSeeExitOK = false;
             
-            unsigned nodeIndex = 0;
-            for (; nodeIndex < block->size() && !block->at(nodeIndex)->origin.forExit.isSet(); nodeIndex++) { }
-            
-            VALIDATE((block), nodeIndex < block->size());
-            
-            for (; nodeIndex < block->size(); nodeIndex++)
-                VALIDATE((block->at(nodeIndex)), block->at(nodeIndex)->origin.forExit.isSet());
-            
             for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
                 Node* node = block->at(nodeIndex);
+                didSeeExitOK |= node->origin.exitOK;
                 switch (node->op()) {
                 case Phi:
-                    VALIDATE((node), !node->origin.forExit.isSet());
+                    // Phi cannot exit, and it would be wrong to hoist anything to the Phi that could
+                    // exit.
+                    VALIDATE((node), !node->origin.exitOK);
+
+                    // It never makes sense to have exitOK anywhere in the block before a Phi. It's only
+                    // OK to exit after all Phis are done.
+                    VALIDATE((node), !didSeeExitOK);
                     break;
                     
                 case GetLocal:
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to