Title: [103218] trunk/Source/_javascript_Core
Revision
103218
Author
[email protected]
Date
2011-12-18 22:36:05 -0800 (Sun, 18 Dec 2011)

Log Message

DFG is too sloppy with register allocation
https://bugs.webkit.org/show_bug.cgi?id=74835

Reviewed by Gavin Barraclough.
        
Added assertions that at the end of a successfully generated basic block,
all use counts should be zero. This revealed a number of bugs:
        
- Array length optimizations were turning a must-generate node into one
  that is not must-generate, but failing to change the ref count
  accordingly.
          
- Indexed property storage optimizations were failing to deref their
  children, or to deref the indexed property storage node itself. Also,
  they used the Phantom node as a replacement. But the Phantom node is
  must-generate, which was causing bizarre issues. So this introduces a
  Nop node, which should be used in cases where you want a node that is
  skipped and has no children.
          
This does not have any significant performance effect, but it should
relieve some register pressure. The main thing this patch adds, though,
are the assertions, which should make it easier to do register allocation
related changes in the future.

* dfg/DFGAbstractState.cpp:
(JSC::DFG::AbstractState::execute):
* dfg/DFGGenerationInfo.h:
(JSC::DFG::GenerationInfo::initConstant):
(JSC::DFG::GenerationInfo::initInteger):
(JSC::DFG::GenerationInfo::initJSValue):
(JSC::DFG::GenerationInfo::initCell):
(JSC::DFG::GenerationInfo::initBoolean):
(JSC::DFG::GenerationInfo::initDouble):
(JSC::DFG::GenerationInfo::initStorage):
(JSC::DFG::GenerationInfo::use):
* dfg/DFGGraph.h:
(JSC::DFG::Graph::clearAndDerefChild1):
(JSC::DFG::Graph::clearAndDerefChild2):
(JSC::DFG::Graph::clearAndDerefChild3):
* dfg/DFGNode.h:
(JSC::DFG::Node::deref):
* dfg/DFGPropagator.cpp:
(JSC::DFG::Propagator::propagateNodePredictions):
(JSC::DFG::Propagator::fixupNode):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (103217 => 103218)


--- trunk/Source/_javascript_Core/ChangeLog	2011-12-19 06:26:46 UTC (rev 103217)
+++ trunk/Source/_javascript_Core/ChangeLog	2011-12-19 06:36:05 UTC (rev 103218)
@@ -1,3 +1,56 @@
+2011-12-18  Filip Pizlo  <[email protected]>
+
+        DFG is too sloppy with register allocation
+        https://bugs.webkit.org/show_bug.cgi?id=74835
+
+        Reviewed by Gavin Barraclough.
+        
+        Added assertions that at the end of a successfully generated basic block,
+        all use counts should be zero. This revealed a number of bugs:
+        
+        - Array length optimizations were turning a must-generate node into one
+          that is not must-generate, but failing to change the ref count
+          accordingly.
+          
+        - Indexed property storage optimizations were failing to deref their
+          children, or to deref the indexed property storage node itself. Also,
+          they used the Phantom node as a replacement. But the Phantom node is
+          must-generate, which was causing bizarre issues. So this introduces a
+          Nop node, which should be used in cases where you want a node that is
+          skipped and has no children.
+          
+        This does not have any significant performance effect, but it should
+        relieve some register pressure. The main thing this patch adds, though,
+        are the assertions, which should make it easier to do register allocation
+        related changes in the future.
+
+        * dfg/DFGAbstractState.cpp:
+        (JSC::DFG::AbstractState::execute):
+        * dfg/DFGGenerationInfo.h:
+        (JSC::DFG::GenerationInfo::initConstant):
+        (JSC::DFG::GenerationInfo::initInteger):
+        (JSC::DFG::GenerationInfo::initJSValue):
+        (JSC::DFG::GenerationInfo::initCell):
+        (JSC::DFG::GenerationInfo::initBoolean):
+        (JSC::DFG::GenerationInfo::initDouble):
+        (JSC::DFG::GenerationInfo::initStorage):
+        (JSC::DFG::GenerationInfo::use):
+        * dfg/DFGGraph.h:
+        (JSC::DFG::Graph::clearAndDerefChild1):
+        (JSC::DFG::Graph::clearAndDerefChild2):
+        (JSC::DFG::Graph::clearAndDerefChild3):
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::deref):
+        * dfg/DFGPropagator.cpp:
+        (JSC::DFG::Propagator::propagateNodePredictions):
+        (JSC::DFG::Propagator::fixupNode):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+
 2011-12-18  Benjamin Poulain  <[email protected]>
 
         Remove the duplicated code from ASCIICType.h

Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractState.cpp (103217 => 103218)


--- trunk/Source/_javascript_Core/dfg/DFGAbstractState.cpp	2011-12-19 06:26:46 UTC (rev 103217)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractState.cpp	2011-12-19 06:36:05 UTC (rev 103218)
@@ -892,6 +892,7 @@
             
     case Phantom:
     case InlineStart:
+    case Nop:
         break;
     }
     

Modified: trunk/Source/_javascript_Core/dfg/DFGGenerationInfo.h (103217 => 103218)


--- trunk/Source/_javascript_Core/dfg/DFGGenerationInfo.h	2011-12-19 06:26:46 UTC (rev 103217)
+++ trunk/Source/_javascript_Core/dfg/DFGGenerationInfo.h	2011-12-19 06:36:05 UTC (rev 103218)
@@ -60,6 +60,7 @@
         m_registerFormat = DataFormatNone;
         m_spillFormat = DataFormatNone;
         m_canFill = true;
+        ASSERT(m_useCount);
     }
     void initInteger(NodeIndex nodeIndex, uint32_t useCount, GPRReg gpr)
     {
@@ -69,6 +70,7 @@
         m_spillFormat = DataFormatNone;
         m_canFill = false;
         u.gpr = gpr;
+        ASSERT(m_useCount);
     }
 #if USE(JSVALUE64)
     void initJSValue(NodeIndex nodeIndex, uint32_t useCount, GPRReg gpr, DataFormat format = DataFormatJS)
@@ -81,6 +83,7 @@
         m_spillFormat = DataFormatNone;
         m_canFill = false;
         u.gpr = gpr;
+        ASSERT(m_useCount);
     }
 #elif USE(JSVALUE32_64)
     void initJSValue(NodeIndex nodeIndex, uint32_t useCount, GPRReg tagGPR, GPRReg payloadGPR, DataFormat format = DataFormatJS)
@@ -94,6 +97,7 @@
         m_canFill = false;
         u.v.tagGPR = tagGPR;
         u.v.payloadGPR = payloadGPR;
+        ASSERT(m_useCount);
     }
 #endif
     void initCell(NodeIndex nodeIndex, uint32_t useCount, GPRReg gpr)
@@ -104,6 +108,7 @@
         m_spillFormat = DataFormatNone;
         m_canFill = false;
         u.gpr = gpr;
+        ASSERT(m_useCount);
     }
     void initBoolean(NodeIndex nodeIndex, uint32_t useCount, GPRReg gpr)
     {
@@ -113,6 +118,7 @@
         m_spillFormat = DataFormatNone;
         m_canFill = false;
         u.gpr = gpr;
+        ASSERT(m_useCount);
     }
     void initDouble(NodeIndex nodeIndex, uint32_t useCount, FPRReg fpr)
     {
@@ -123,6 +129,7 @@
         m_spillFormat = DataFormatNone;
         m_canFill = false;
         u.fpr = fpr;
+        ASSERT(m_useCount);
     }
     void initStorage(NodeIndex nodeIndex, uint32_t useCount, GPRReg gpr)
     {
@@ -132,6 +139,7 @@
         m_spillFormat = DataFormatNone;
         m_canFill = false;
         u.gpr = gpr;
+        ASSERT(m_useCount);
     }
 
     // Get the index of the node that produced this value.
@@ -142,6 +150,7 @@
     // associated machine registers may be freed.
     bool use()
     {
+        ASSERT(m_useCount);
         return !--m_useCount;
     }
 

Modified: trunk/Source/_javascript_Core/dfg/DFGGraph.h (103217 => 103218)


--- trunk/Source/_javascript_Core/dfg/DFGGraph.h	2011-12-19 06:26:46 UTC (rev 103217)
+++ trunk/Source/_javascript_Core/dfg/DFGGraph.h	2011-12-19 06:36:05 UTC (rev 103218)
@@ -79,7 +79,31 @@
         if (node.ref())
             refChildren(nodeIndex);
     }
+    
+    void clearAndDerefChild1(Node& node)
+    {
+        if (node.children.fixed.child1 == NoNode)
+            return;
+        at(node.children.fixed.child1).deref();
+        node.children.fixed.child1 = NoNode;
+    }
 
+    void clearAndDerefChild2(Node& node)
+    {
+        if (node.children.fixed.child2 == NoNode)
+            return;
+        at(node.children.fixed.child2).deref();
+        node.children.fixed.child2 = NoNode;
+    }
+
+    void clearAndDerefChild3(Node& node)
+    {
+        if (node.children.fixed.child3 == NoNode)
+            return;
+        at(node.children.fixed.child3).deref();
+        node.children.fixed.child3 = NoNode;
+    }
+
 #ifndef NDEBUG
     // CodeBlock is optional, but may allow additional information to be dumped (e.g. Identifier names).
     void dump(CodeBlock* = 0);

Modified: trunk/Source/_javascript_Core/dfg/DFGNode.h (103217 => 103218)


--- trunk/Source/_javascript_Core/dfg/DFGNode.h	2011-12-19 06:26:46 UTC (rev 103217)
+++ trunk/Source/_javascript_Core/dfg/DFGNode.h	2011-12-19 06:36:05 UTC (rev 103218)
@@ -178,6 +178,7 @@
     macro(GetLocal, NodeResultJS) \
     macro(SetLocal, 0) \
     macro(Phantom, NodeMustGenerate) \
+    macro(Nop, 0) \
     macro(Phi, 0) \
     macro(Flush, NodeMustGenerate) \
     \
@@ -835,6 +836,11 @@
         m_refCount = refCount;
     }
     
+    void deref()
+    {
+        m_refCount--;
+    }
+    
     NodeIndex child1()
     {
         ASSERT(!(op & NodeHasVarArgs));

Modified: trunk/Source/_javascript_Core/dfg/DFGPropagator.cpp (103217 => 103218)


--- trunk/Source/_javascript_Core/dfg/DFGPropagator.cpp	2011-12-19 06:26:46 UTC (rev 103217)
+++ trunk/Source/_javascript_Core/dfg/DFGPropagator.cpp	2011-12-19 06:36:05 UTC (rev 103218)
@@ -624,6 +624,7 @@
         // These gets ignored because it doesn't do anything.
         case Phantom:
         case InlineStart:
+        case Nop:
             break;
 #else
         default:
@@ -915,22 +916,24 @@
                 node.op = GetFloat64ArrayLength;
             else
                 ASSERT_NOT_REACHED();
+            node.deref(); // No longer MustGenerate
             break;
         }
         case GetIndexedPropertyStorage: {
             PredictedType basePrediction = m_graph[node.child2()].prediction();
             if (!(basePrediction & PredictInt32) && basePrediction) {
-                node.op = Phantom;
-                node.children.fixed.child1 = NoNode;
-                node.children.fixed.child2 = NoNode;
-                node.children.fixed.child3 = NoNode;
+                node.op = Nop;
+                m_graph.clearAndDerefChild1(node);
+                m_graph.clearAndDerefChild2(node);
+                m_graph.clearAndDerefChild3(node);
+                node.setRefCount(0);
             }
             break;
         }
         case GetByVal:
         case StringCharAt:
         case StringCharCodeAt: {
-            if (node.child3() != NoNode && m_graph[node.child3()].op == Phantom)
+            if (node.child3() != NoNode && m_graph[node.child3()].op == Nop)
                 node.children.fixed.child3 = NoNode;
             break;
         }

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (103217 => 103218)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2011-12-19 06:26:46 UTC (rev 103217)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2011-12-19 06:36:05 UTC (rev 103218)
@@ -1042,6 +1042,14 @@
         if (node.shouldGenerate())
             checkConsistency();
     }
+    
+    // Perform the most basic verification that children have been used correctly.
+#if !ASSERT_DISABLED
+    for (unsigned index = 0; index < m_generationInfo.size(); ++index) {
+        GenerationInfo& info = m_generationInfo[index];
+        ASSERT(!info.alive());
+    }
+#endif
 }
 
 // If we are making type predictions about our arguments then

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (103217 => 103218)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2011-12-19 06:26:46 UTC (rev 103217)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2011-12-19 06:36:05 UTC (rev 103218)
@@ -3863,10 +3863,14 @@
         break;
 
     case InlineStart:
+    case Nop:
         ASSERT_NOT_REACHED();
         break;
     }
 
+    if (!m_compileOkay)
+        return;
+    
     if (node.hasResult() && node.mustGenerate())
         use(m_compileIndex);
 }

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (103217 => 103218)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2011-12-19 06:26:46 UTC (rev 103217)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2011-12-19 06:36:05 UTC (rev 103218)
@@ -3796,10 +3796,14 @@
         break;
         
     case InlineStart:
+    case Nop:
         ASSERT_NOT_REACHED();
         break;
     }
 
+    if (!m_compileOkay)
+        return;
+    
     if (node.hasResult() && node.mustGenerate())
         use(m_compileIndex);
 }
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to