Title: [173626] trunk/Source/_javascript_Core
Revision
173626
Author
[email protected]
Date
2014-09-15 12:32:01 -0700 (Mon, 15 Sep 2014)

Log Message

DFG ref count calculation should be reusable
https://bugs.webkit.org/show_bug.cgi?id=136811

Reviewed by Oliver Hunt.
        
Henceforth if you call Graph::computeRefCounts(), a nifty O(n) operation, every Node
will be able to tell you how many places it is used from. Currently only DCE uses this,
but it will be useful for https://bugs.webkit.org/show_bug.cgi?id=136330.

* dfg/DFGDCEPhase.cpp:
(JSC::DFG::DCEPhase::run):
(JSC::DFG::DCEPhase::findTypeCheckRoot): Deleted.
(JSC::DFG::DCEPhase::countNode): Deleted.
(JSC::DFG::DCEPhase::countEdge): Deleted.
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::computeRefCounts):
* dfg/DFGGraph.h:

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (173625 => 173626)


--- trunk/Source/_javascript_Core/ChangeLog	2014-09-15 18:45:28 UTC (rev 173625)
+++ trunk/Source/_javascript_Core/ChangeLog	2014-09-15 19:32:01 UTC (rev 173626)
@@ -1,3 +1,23 @@
+2014-09-14  Filip Pizlo  <[email protected]>
+
+        DFG ref count calculation should be reusable
+        https://bugs.webkit.org/show_bug.cgi?id=136811
+
+        Reviewed by Oliver Hunt.
+        
+        Henceforth if you call Graph::computeRefCounts(), a nifty O(n) operation, every Node
+        will be able to tell you how many places it is used from. Currently only DCE uses this,
+        but it will be useful for https://bugs.webkit.org/show_bug.cgi?id=136330.
+
+        * dfg/DFGDCEPhase.cpp:
+        (JSC::DFG::DCEPhase::run):
+        (JSC::DFG::DCEPhase::findTypeCheckRoot): Deleted.
+        (JSC::DFG::DCEPhase::countNode): Deleted.
+        (JSC::DFG::DCEPhase::countEdge): Deleted.
+        * dfg/DFGGraph.cpp:
+        (JSC::DFG::Graph::computeRefCounts):
+        * dfg/DFGGraph.h:
+
 2014-09-12  Michael Saboff  <[email protected]>
 
         Merge JSGlobalObject::reset() into ::init()

Modified: trunk/Source/_javascript_Core/dfg/DFGDCEPhase.cpp (173625 => 173626)


--- trunk/Source/_javascript_Core/dfg/DFGDCEPhase.cpp	2014-09-15 18:45:28 UTC (rev 173625)
+++ trunk/Source/_javascript_Core/dfg/DFGDCEPhase.cpp	2014-09-15 19:32:01 UTC (rev 173626)
@@ -48,73 +48,8 @@
     {
         ASSERT(m_graph.m_form == ThreadedCPS || m_graph.m_form == SSA);
         
-        // First reset the counts to 0 for all nodes.
-        //
-        // Also take this opportunity to pretend that Check nodes are not NodeMustGenerate. Check
-        // nodes are MustGenerate because they are executed for effect, but they follow the same
-        // DCE rules as nodes that aren't MustGenerate: they only contribute to the ref count of
-        // their children if the edges require checks. Non-checking edges are removed. Note that
-        // for any Checks left over, this phase will turn them back into NodeMustGenerate.
-        for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
-            BasicBlock* block = m_graph.block(blockIndex);
-            if (!block)
-                continue;
-            for (unsigned indexInBlock = block->size(); indexInBlock--;) {
-                Node* node = block->at(indexInBlock);
-                if (node->op() == Check)
-                    node->clearFlags(NodeMustGenerate);
-                node->setRefCount(0);
-            }
-            for (unsigned phiIndex = block->phis.size(); phiIndex--;)
-                block->phis[phiIndex]->setRefCount(0);
-        }
-    
-        // Now find the roots:
-        // - Nodes that are must-generate.
-        // - Nodes that are reachable from type checks.
-        // Set their ref counts to 1 and put them on the worklist.
-        for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
-            BasicBlock* block = m_graph.block(blockIndex);
-            if (!block)
-                continue;
-            for (unsigned indexInBlock = block->size(); indexInBlock--;) {
-                Node* node = block->at(indexInBlock);
-                DFG_NODE_DO_TO_CHILDREN(m_graph, node, findTypeCheckRoot);
-                if (!(node->flags() & NodeMustGenerate))
-                    continue;
-                if (!node->postfixRef())
-                    m_worklist.append(node);
-            }
-        }
+        m_graph.computeRefCounts();
         
-        while (!m_worklist.isEmpty()) {
-            while (!m_worklist.isEmpty()) {
-                Node* node = m_worklist.last();
-                m_worklist.removeLast();
-                ASSERT(node->shouldGenerate()); // It should not be on the worklist unless it's ref'ed.
-                DFG_NODE_DO_TO_CHILDREN(m_graph, node, countEdge);
-            }
-            
-            if (m_graph.m_form == SSA) {
-                // Find Phi->Upsilon edges, which are represented as meta-data in the
-                // Upsilon.
-                for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
-                    BasicBlock* block = m_graph.block(blockIndex);
-                    if (!block)
-                        continue;
-                    for (unsigned nodeIndex = block->size(); nodeIndex--;) {
-                        Node* node = block->at(nodeIndex);
-                        if (node->op() != Upsilon)
-                            continue;
-                        if (node->shouldGenerate())
-                            continue;
-                        if (node->phi()->shouldGenerate())
-                            countNode(node);
-                    }
-                }
-            }
-        }
-        
         if (m_graph.m_form == SSA) {
             for (BasicBlock* block : m_graph.blocksInPreOrder())
                 fixupBlock(block);
@@ -157,31 +92,6 @@
     }
 
 private:
-    void findTypeCheckRoot(Node*, Edge edge)
-    {
-        // We may have an "unproved" untyped use for code that is unreachable. The CFA
-        // will just not have gotten around to it.
-        if (edge.isProved() || edge.willNotHaveCheck())
-            return;
-        if (!edge->postfixRef())
-            m_worklist.append(edge.node());
-    }
-    
-    void countNode(Node* node)
-    {
-        if (node->postfixRef())
-            return;
-        m_worklist.append(node);
-    }
-    
-    void countEdge(Node*, Edge edge)
-    {
-        // Don't count edges that are already counted for their type checks.
-        if (!(edge.isProved() || edge.willNotHaveCheck()))
-            return;
-        countNode(edge.node());
-    }
-    
     void fixupBlock(BasicBlock* block)
     {
         if (!block)
@@ -327,7 +237,6 @@
         }
     }
     
-    Vector<Node*, 128> m_worklist;
     InsertionSet m_insertionSet;
 };
 

Modified: trunk/Source/_javascript_Core/dfg/DFGGraph.cpp (173625 => 173626)


--- trunk/Source/_javascript_Core/dfg/DFGGraph.cpp	2014-09-15 18:45:28 UTC (rev 173625)
+++ trunk/Source/_javascript_Core/dfg/DFGGraph.cpp	2014-09-15 19:32:01 UTC (rev 173626)
@@ -562,6 +562,124 @@
     determineReachability();
 }
 
+namespace {
+
+class RefCountCalculator {
+public:
+    RefCountCalculator(Graph& graph)
+        : m_graph(graph)
+    {
+    }
+    
+    void calculate()
+    {
+        // First reset the counts to 0 for all nodes.
+        //
+        // Also take this opportunity to pretend that Check nodes are not NodeMustGenerate. Check
+        // nodes are MustGenerate because they are executed for effect, but they follow the same
+        // DCE rules as nodes that aren't MustGenerate: they only contribute to the ref count of
+        // their children if the edges require checks. Non-checking edges are removed. Note that
+        // for any Checks left over, this phase will turn them back into NodeMustGenerate.
+        for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
+            BasicBlock* block = m_graph.block(blockIndex);
+            if (!block)
+                continue;
+            for (unsigned indexInBlock = block->size(); indexInBlock--;)
+                block->at(indexInBlock)->setRefCount(0);
+            for (unsigned phiIndex = block->phis.size(); phiIndex--;)
+                block->phis[phiIndex]->setRefCount(0);
+        }
+    
+        // Now find the roots:
+        // - Nodes that are must-generate.
+        // - Nodes that are reachable from type checks.
+        // Set their ref counts to 1 and put them on the worklist.
+        for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
+            BasicBlock* block = m_graph.block(blockIndex);
+            if (!block)
+                continue;
+            for (unsigned indexInBlock = block->size(); indexInBlock--;) {
+                Node* node = block->at(indexInBlock);
+                DFG_NODE_DO_TO_CHILDREN(m_graph, node, findTypeCheckRoot);
+                if (!(node->flags() & NodeMustGenerate))
+                    continue;
+                if (node->op() == Check) {
+                    // We don't treat Check nodes as MustGenerate. We will gladly
+                    // kill them off in this phase.
+                    continue;
+                }
+                if (!node->postfixRef())
+                    m_worklist.append(node);
+            }
+        }
+        
+        while (!m_worklist.isEmpty()) {
+            while (!m_worklist.isEmpty()) {
+                Node* node = m_worklist.last();
+                m_worklist.removeLast();
+                ASSERT(node->shouldGenerate()); // It should not be on the worklist unless it's ref'ed.
+                DFG_NODE_DO_TO_CHILDREN(m_graph, node, countEdge);
+            }
+            
+            if (m_graph.m_form == SSA) {
+                // Find Phi->Upsilon edges, which are represented as meta-data in the
+                // Upsilon.
+                for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
+                    BasicBlock* block = m_graph.block(blockIndex);
+                    if (!block)
+                        continue;
+                    for (unsigned nodeIndex = block->size(); nodeIndex--;) {
+                        Node* node = block->at(nodeIndex);
+                        if (node->op() != Upsilon)
+                            continue;
+                        if (node->shouldGenerate())
+                            continue;
+                        if (node->phi()->shouldGenerate())
+                            countNode(node);
+                    }
+                }
+            }
+        }
+    }
+    
+private:
+    void findTypeCheckRoot(Node*, Edge edge)
+    {
+        // We may have an "unproved" untyped use for code that is unreachable. The CFA
+        // will just not have gotten around to it.
+        if (edge.isProved() || edge.willNotHaveCheck())
+            return;
+        if (!edge->postfixRef())
+            m_worklist.append(edge.node());
+    }
+    
+    void countNode(Node* node)
+    {
+        if (node->postfixRef())
+            return;
+        m_worklist.append(node);
+    }
+    
+    void countEdge(Node*, Edge edge)
+    {
+        // Don't count edges that are already counted for their type checks.
+        if (!(edge.isProved() || edge.willNotHaveCheck()))
+            return;
+        countNode(edge.node());
+    }
+    
+    Graph& m_graph;
+    Vector<Node*, 128> m_worklist;
+};
+
+} // anonymous namespace
+
+void Graph::computeRefCounts()
+{
+    RefCountCalculator calculator(*this);
+    calculator.calculate();
+}
+
 void Graph::killBlockAndItsContents(BasicBlock* block)
 {
     for (unsigned phiIndex = block->phis.size(); phiIndex--;)

Modified: trunk/Source/_javascript_Core/dfg/DFGGraph.h (173625 => 173626)


--- trunk/Source/_javascript_Core/dfg/DFGGraph.h	2014-09-15 18:45:28 UTC (rev 173625)
+++ trunk/Source/_javascript_Core/dfg/DFGGraph.h	2014-09-15 19:32:01 UTC (rev 173626)
@@ -570,6 +570,8 @@
     void determineReachability();
     void resetReachability();
     
+    void computeRefCounts();
+    
     unsigned varArgNumChildren(Node* node)
     {
         ASSERT(node->flags() & NodeHasVarArgs);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to