]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - dfg/DFGScoreBoard.h
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / dfg / DFGScoreBoard.h
index 1e44292cd2397a965f3e593d9d54816b1038dd0e..c8795c8a448adda936873ce56a76ba4a065916f6 100644 (file)
@@ -28,7 +28,8 @@
 
 #if ENABLE(DFG_JIT)
 
-#include <dfg/DFGGraph.h>
+#include "DFGGraph.h"
+#include <wtf/BitVector.h>
 #include <wtf/Vector.h>
 
 namespace JSC { namespace DFG {
@@ -42,25 +43,40 @@ namespace JSC { namespace DFG {
 // another node.
 class ScoreBoard {
 public:
-    ScoreBoard(Graph& graph, uint32_t firstTemporary)
-        : m_graph(graph)
-        , m_firstTemporary(firstTemporary)
+    ScoreBoard(unsigned nextMachineLocal)
+        : m_highWatermark(nextMachineLocal + 1)
     {
+        m_used.fill(max(), nextMachineLocal);
+        m_free.reserveCapacity(nextMachineLocal);
     }
 
-#if DFG_CONSISTENCY_CHECK
     ~ScoreBoard()
     {
-        // Every VirtualRegister that was allocated should now be free.
-        ASSERT(m_used.size() == m_free.size());
-        // Every entry in the used list should be available in the free list.
+        assertClear();
+    }
+    
+    void sortFree()
+    {
+        std::sort(m_free.begin(), m_free.end());
+    }
+    
+    void assertClear()
+    {
+        if (ASSERT_DISABLED)
+            return;
+        
+        // For every entry in the used list the use count of the virtual register should be zero, or max, due to it being a preserved local.
         for (size_t i = 0; i < m_used.size(); ++i)
-            ASSERT(m_free.contains(i));
-        // For every entry in the used list the use count of the virtual register should be zero.
+            RELEASE_ASSERT(!m_used[i] || m_used[i] == max());
+        // For every entry in the free list, the use count should be zero.
         for (size_t i = 0; i < m_free.size(); ++i)
-            ASSERT(!m_used[i]);
+            RELEASE_ASSERT(!m_used[m_free[i]]);
+        // There must not be duplicates in the free list.
+        for (size_t i = 0; i < m_free.size(); ++i) {
+            for (size_t j = i + 1; j < m_free.size(); ++j)
+                RELEASE_ASSERT(m_free[i] != m_free[j]);
+        }
     }
-#endif
 
     VirtualRegister allocate()
     {
@@ -71,26 +87,28 @@ public:
             m_free.removeLast();
             // Use count must have hit zero for it to have been added to the free list!
             ASSERT(!m_used[index]);
-            return (VirtualRegister)(m_firstTemporary + index);
+            m_highWatermark = std::max(m_highWatermark, static_cast<unsigned>(index) + 1);
+            return virtualRegisterForLocal(index);
         }
 
         // Allocate a new VirtualRegister, and add a corresponding entry to m_used.
-        size_t next = allocatedCount();
+        size_t next = m_used.size();
         m_used.append(0);
-        return (VirtualRegister)(m_firstTemporary + next);
+        m_highWatermark = std::max(m_highWatermark, static_cast<unsigned>(next) + 1);
+        return virtualRegisterForLocal(next);
     }
 
-    // Increment the usecount for the VirtualRegsiter associated with 'child',
-    // if it reaches the node's refcount, free the VirtualRegsiter.
-    void use(NodeIndex child)
+    // Increment the usecount for the VirtualRegister associated with 'child',
+    // if it reaches the node's refcount, free the VirtualRegister.
+    void use(Node* child)
     {
-        if (child == NoNode)
+        if (!child)
             return;
 
         // Find the virtual register number for this child, increment its use count.
-        Node& node = m_graph[child];
-        uint32_t index = node.virtualRegister() - m_firstTemporary;
-        if (node.refCount() == ++m_used[index]) {
+        uint32_t index = child->virtualRegister().toLocal();
+        ASSERT(m_used[index] != max());
+        if (child->refCount() == ++m_used[index]) {
             // If the use count in the scoreboard reaches the use count for the node,
             // then this was its last use; the virtual register is now free.
             // Clear the use count & add to the free list.
@@ -98,40 +116,57 @@ public:
             m_free.append(index);
         }
     }
-
-    unsigned allocatedCount()
+    void use(Edge child)
     {
-        // m_used contains an entry for every allocated VirtualRegister.
-        return m_used.size();
+        use(child.node());
+    }
+    
+    void useIfHasResult(Edge child)
+    {
+        if (!child)
+            return;
+        if (!child->hasResult())
+            return;
+        use(child);
     }
 
+    unsigned highWatermark()
+    {
+        return m_highWatermark;
+    }
+    
 #ifndef NDEBUG
     void dump()
     {
-        printf("    USED: [ ");
+        dataLogF("    USED: [ ");
         for (unsigned i = 0; i < m_used.size(); ++i) {
-            if (!m_free.contains(i))
-                printf("%d:%d ", m_firstTemporary + i, m_used[i]);
+            if (!m_free.contains(i)) {
+                dataLogF("%d:", i);
+                if (m_used[i] == max())
+                    dataLogF("local ");
+                else
+                    dataLogF("%d ", m_used[i]);
+            }
         }
-        printf("]\n");
+        dataLogF("]\n");
 
-        printf("    FREE: [ ");
+        dataLogF("    FREE: [ ");
         for (unsigned i = 0; i < m_used.size(); ++i) {
-            if (m_free.contains(i)) {
+            if (m_free.contains(i) && m_used[i] != max()) {
                 ASSERT(!m_used[i]);
-                printf("%d ", m_firstTemporary + i);
+                dataLogF("%d ", i);
             }
         }
-        printf("]\n");
+        dataLogF("]\n");
     }
 
 #endif
 
 private:
-    // The graph, so we can get refCounts for nodes, to determine when values are dead.
-    Graph& m_graph;
-    // The first VirtualRegsiter to be used as a temporary.
-    uint32_t m_firstTemporary;
+    static uint32_t max() { return std::numeric_limits<uint32_t>::max(); }
+    
+    // The size of the span of virtual registers that this code block will use.
+    unsigned m_highWatermark;
     
     // For every virtual register that has been allocated (either currently alive, or in
     // the free list), we keep a count of the number of remaining uses until it is dead