Nodes should have an optional epoch field
authorfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 23 Apr 2015 02:36:08 +0000 (02:36 +0000)
committerfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 23 Apr 2015 02:36:08 +0000 (02:36 +0000)
https://bugs.webkit.org/show_bug.cgi?id=144084

Reviewed by Ryosuke Niwa and Mark Lam.

This makes it easier to do epoch-based analyses on nodes. I plan to do just that in
https://bugs.webkit.org/show_bug.cgi?id=143735. Currently the epoch field is not yet
used.

* dfg/DFGCPSRethreadingPhase.cpp:
(JSC::DFG::CPSRethreadingPhase::canonicalizeGetLocalFor):
* dfg/DFGCSEPhase.cpp:
* dfg/DFGEpoch.h:
(JSC::DFG::Epoch::fromUnsigned):
(JSC::DFG::Epoch::toUnsigned):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::clearReplacements):
(JSC::DFG::Graph::clearEpochs):
* dfg/DFGGraph.h:
(JSC::DFG::Graph::performSubstitutionForEdge):
* dfg/DFGNode.h:
(JSC::DFG::Node::Node):
(JSC::DFG::Node::replaceWith):
(JSC::DFG::Node::replacement):
(JSC::DFG::Node::setReplacement):
(JSC::DFG::Node::epoch):
(JSC::DFG::Node::setEpoch):
* dfg/DFGSSAConversionPhase.cpp:
(JSC::DFG::SSAConversionPhase::run):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@183162 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/dfg/DFGCPSRethreadingPhase.cpp
Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
Source/JavaScriptCore/dfg/DFGEpoch.h
Source/JavaScriptCore/dfg/DFGGraph.cpp
Source/JavaScriptCore/dfg/DFGGraph.h
Source/JavaScriptCore/dfg/DFGNode.h
Source/JavaScriptCore/dfg/DFGSSAConversionPhase.cpp

index fa2ec15..0b83533 100644 (file)
@@ -1,3 +1,35 @@
+2015-04-22  Filip Pizlo  <fpizlo@apple.com>
+
+        Nodes should have an optional epoch field
+        https://bugs.webkit.org/show_bug.cgi?id=144084
+
+        Reviewed by Ryosuke Niwa and Mark Lam.
+        
+        This makes it easier to do epoch-based analyses on nodes. I plan to do just that in
+        https://bugs.webkit.org/show_bug.cgi?id=143735. Currently the epoch field is not yet
+        used.
+
+        * dfg/DFGCPSRethreadingPhase.cpp:
+        (JSC::DFG::CPSRethreadingPhase::canonicalizeGetLocalFor):
+        * dfg/DFGCSEPhase.cpp:
+        * dfg/DFGEpoch.h:
+        (JSC::DFG::Epoch::fromUnsigned):
+        (JSC::DFG::Epoch::toUnsigned):
+        * dfg/DFGGraph.cpp:
+        (JSC::DFG::Graph::clearReplacements):
+        (JSC::DFG::Graph::clearEpochs):
+        * dfg/DFGGraph.h:
+        (JSC::DFG::Graph::performSubstitutionForEdge):
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::Node):
+        (JSC::DFG::Node::replaceWith):
+        (JSC::DFG::Node::replacement):
+        (JSC::DFG::Node::setReplacement):
+        (JSC::DFG::Node::epoch):
+        (JSC::DFG::Node::setEpoch):
+        * dfg/DFGSSAConversionPhase.cpp:
+        (JSC::DFG::SSAConversionPhase::run):
+
 2015-04-22  Mark Lam  <mark.lam@apple.com>
 
         Fix assertion failure and race condition in Options::dumpSourceAtDFGTime().
index c82a5d2..3489424 100644 (file)
@@ -194,12 +194,12 @@ private:
             
             if (otherNode->op() == GetLocal) {
                 // Replace all references to this GetLocal with otherNode.
-                node->replacement = otherNode;
+                node->setReplacement(otherNode);
                 return;
             }
             
             ASSERT(otherNode->op() == SetLocal);
-            node->replacement = otherNode->child1().node();
+            node->setReplacement(otherNode->child1().node());
             return;
         }
         
index 4148bd8..0ceaa25 100644 (file)
@@ -235,7 +235,7 @@ private:
             
                 if (m_node->op() == Identity) {
                     m_node->convertToCheck();
-                    m_node->replacement = m_node->child1().node();
+                    m_node->setReplacement(m_node->child1().node());
                     m_changed = true;
                 } else {
                     // This rule only makes sense for local CSE, since in SSA form we have already
@@ -438,7 +438,7 @@ public:
                 
                 if (m_node->op() == Identity) {
                     m_node->convertToCheck();
-                    m_node->replacement = m_node->child1().node();
+                    m_node->setReplacement(m_node->child1().node());
                     m_changed = true;
                 } else
                     clobberize(m_graph, m_node, *this);
index adb0955..59a441c 100644 (file)
@@ -41,6 +41,18 @@ public:
     {
     }
     
+    static Epoch fromUnsigned(unsigned value)
+    {
+        Epoch result;
+        result.m_epoch = value;
+        return result;
+    }
+    
+    unsigned toUnsigned() const
+    {
+        return m_epoch;
+    }
+    
     static Epoch first()
     {
         Epoch result;
index 1e7df0f..1dd4197 100644 (file)
@@ -832,9 +832,22 @@ void Graph::clearReplacements()
         if (!block)
             continue;
         for (unsigned phiIndex = block->phis.size(); phiIndex--;)
-            block->phis[phiIndex]->replacement = 0;
+            block->phis[phiIndex]->setReplacement(nullptr);
         for (unsigned nodeIndex = block->size(); nodeIndex--;)
-            block->at(nodeIndex)->replacement = 0;
+            block->at(nodeIndex)->setReplacement(nullptr);
+    }
+}
+
+void Graph::clearEpochs()
+{
+    for (BlockIndex blockIndex = numBlocks(); blockIndex--;) {
+        BasicBlock* block = m_blocks[blockIndex].get();
+        if (!block)
+            continue;
+        for (unsigned phiIndex = block->phis.size(); phiIndex--;)
+            block->phis[phiIndex]->setEpoch(Epoch());
+        for (unsigned nodeIndex = block->size(); nodeIndex--;)
+            block->at(nodeIndex)->setEpoch(Epoch());
     }
 }
 
index 07b00c9..d37140d 100644 (file)
@@ -162,7 +162,7 @@ public:
             return;
         
         // Check if there is any replacement.
-        Node* replacement = child->replacement;
+        Node* replacement = child->replacement();
         if (!replacement)
             return;
         
@@ -563,6 +563,7 @@ public:
     void clearFlagsOnAllNodes(NodeFlags);
     
     void clearReplacements();
+    void clearEpochs();
     void initializeNodeOwners();
     
     BlockList blocksInPreOrder();
index 53f1066..5bd8c4a 100644 (file)
@@ -35,6 +35,7 @@
 #include "DFGArithMode.h"
 #include "DFGArrayMode.h"
 #include "DFGCommon.h"
+#include "DFGEpoch.h"
 #include "DFGLazyJSValue.h"
 #include "DFGNodeFlags.h"
 #include "DFGNodeOrigin.h"
@@ -245,9 +246,9 @@ struct Node {
         , m_virtualRegister(VirtualRegister())
         , m_refCount(1)
         , m_prediction(SpecNone)
-        , replacement(nullptr)
         , owner(nullptr)
     {
+        m_misc.replacement = nullptr;
         setOpAndDefaultFlags(op);
     }
     
@@ -260,9 +261,9 @@ struct Node {
         , m_prediction(SpecNone)
         , m_opInfo(0)
         , m_opInfo2(0)
-        , replacement(nullptr)
         , owner(nullptr)
     {
+        m_misc.replacement = nullptr;
         setOpAndDefaultFlags(op);
         ASSERT(!(m_flags & NodeHasVarArgs));
     }
@@ -276,9 +277,9 @@ struct Node {
         , m_prediction(SpecNone)
         , m_opInfo(0)
         , m_opInfo2(0)
-        , replacement(nullptr)
         , owner(nullptr)
     {
+        m_misc.replacement = nullptr;
         setOpAndDefaultFlags(op);
         setResult(result);
         ASSERT(!(m_flags & NodeHasVarArgs));
@@ -293,9 +294,9 @@ struct Node {
         , m_prediction(SpecNone)
         , m_opInfo(imm.m_value)
         , m_opInfo2(0)
-        , replacement(nullptr)
         , owner(nullptr)
     {
+        m_misc.replacement = nullptr;
         setOpAndDefaultFlags(op);
         ASSERT(!(m_flags & NodeHasVarArgs));
     }
@@ -309,9 +310,9 @@ struct Node {
         , m_prediction(SpecNone)
         , m_opInfo(imm.m_value)
         , m_opInfo2(0)
-        , replacement(nullptr)
         , owner(nullptr)
     {
+        m_misc.replacement = nullptr;
         setOpAndDefaultFlags(op);
         setResult(result);
         ASSERT(!(m_flags & NodeHasVarArgs));
@@ -326,9 +327,9 @@ struct Node {
         , m_prediction(SpecNone)
         , m_opInfo(imm1.m_value)
         , m_opInfo2(imm2.m_value)
-        , replacement(nullptr)
         , owner(nullptr)
     {
+        m_misc.replacement = nullptr;
         setOpAndDefaultFlags(op);
         ASSERT(!(m_flags & NodeHasVarArgs));
     }
@@ -342,9 +343,9 @@ struct Node {
         , m_prediction(SpecNone)
         , m_opInfo(imm1.m_value)
         , m_opInfo2(imm2.m_value)
-        , replacement(nullptr)
         , owner(nullptr)
     {
+        m_misc.replacement = nullptr;
         setOpAndDefaultFlags(op);
         ASSERT(m_flags & NodeHasVarArgs);
     }
@@ -425,7 +426,7 @@ struct Node {
     void replaceWith(Node* other)
     {
         convertToPhantom();
-        replacement = other;
+        setReplacement(other);
     }
 
     void convertToIdentity();
@@ -1936,6 +1937,26 @@ struct Node {
         return reinterpret_cast<BasicBlockLocation*>(m_opInfo);
     }
     
+    Node* replacement() const
+    {
+        return m_misc.replacement;
+    }
+    
+    void setReplacement(Node* replacement)
+    {
+        m_misc.replacement = replacement;
+    }
+    
+    Epoch epoch() const
+    {
+        return Epoch::fromUnsigned(m_misc.epoch);
+    }
+    
+    void setEpoch(Epoch epoch)
+    {
+        m_misc.epoch = epoch.toUnsigned();
+    }
+    
     void dumpChildren(PrintStream& out)
     {
         if (!child1())
@@ -1979,12 +2000,17 @@ public:
     // will tell you which basic block a node belongs to. You cannot rely on this persisting
     // across transformations unless you do the maintenance work yourself. Other phases use
     // Node::replacement, but they do so manually: first you do Graph::clearReplacements()
-    // and then you set, and use, replacement's yourself.
+    // and then you set, and use, replacement's yourself. Same thing for epoch.
     //
     // Bottom line: don't use these fields unless you initialize them yourself, or by
     // calling some appropriate methods that initialize them the way you want. Otherwise,
     // these fields are meaningless.
-    Node* replacement;
+private:
+    union {
+        Node* replacement;
+        unsigned epoch;
+    } m_misc;
+public:
     BasicBlock* owner;
 };
 
index 8ed8eb5..835e348 100644 (file)
@@ -227,13 +227,13 @@ public:
                     }
                     
                     Node* node = def->value();
-                    if (node->replacement) {
+                    if (node->replacement()) {
                         // This will occur when a SetLocal had a GetLocal as its source. The
                         // GetLocal would get replaced with an actual SSA value by the time we get
                         // here. Note that the SSA value with which the GetLocal got replaced
                         // would not in turn have a replacement.
-                        node = node->replacement;
-                        ASSERT(!node->replacement);
+                        node = node->replacement();
+                        ASSERT(!node->replacement());
                     }
                     if (verbose)
                         dataLog("Mapping: ", VirtualRegister(valueForOperand.operandForIndex(i)), " -> ", node, "\n");
@@ -303,7 +303,7 @@ public:
                     node->convertToPhantom();
                     if (verbose)
                         dataLog("Replacing node ", node, " with ", valueForOperand.operand(variable->local()), "\n");
-                    node->replacement = valueForOperand.operand(variable->local());
+                    node->setReplacement(valueForOperand.operand(variable->local()));
                     break;
                 }