]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - dfg/DFGRegisterBank.h
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / dfg / DFGRegisterBank.h
index f4fdd50a7197a7a14d7edf9b16e32ebde9147d93..32c1e91eebe6f2e844874a347199095028f6ebb4 100644 (file)
@@ -28,7 +28,9 @@
 
 #if ENABLE(DFG_JIT)
 
-#include <dfg/DFGNode.h>
+#include "DFGCommon.h"
+#include "FPRInfo.h"
+#include "GPRInfo.h"
 
 namespace JSC { namespace DFG {
 
@@ -75,10 +77,24 @@ class RegisterBank {
 
 public:
     RegisterBank()
-        : m_lastAllocated(NUM_REGS - 1)
     {
     }
 
+    // Attempt to allocate a register - this function finds an unlocked
+    // register, locks it, and returns it. If none can be found, this
+    // returns -1 (InvalidGPRReg or InvalidFPRReg).
+    RegID tryAllocate()
+    {
+        VirtualRegister ignored = VirtualRegister();
+        
+        for (uint32_t i = 0; i < NUM_REGS; ++i) {
+            if (!m_data[i].lockCount && !m_data[i].name.isValid())
+                return allocateInternal(i, ignored);
+        }
+        
+        return (RegID)-1;
+    }
+
     // Allocate a register - this function finds an unlocked register,
     // locks it, and returns it. If any named registers exist, one
     // of these should be selected to be allocated. If all unlocked
@@ -95,9 +111,6 @@ public:
         uint32_t currentLowest = NUM_REGS;
         SpillHint currentSpillOrder = SpillHintInvalid;
 
-        // Scan through all register, starting at the last allocated & looping around.
-        ASSERT(m_lastAllocated < NUM_REGS);
-
         // This loop is broken into two halves, looping from the last allocated
         // register (the register returned last time this method was called) to
         // the maximum register value, then from 0 to the last allocated.
@@ -105,7 +118,7 @@ public:
         // thrash, and minimize time spent scanning locked registers in allocation.
         // If a unlocked and unnamed register is found return it immediately.
         // Otherwise, find the first unlocked register with the lowest spillOrder.
-        for (uint32_t i = m_lastAllocated + 1; i < NUM_REGS; ++i) {
+        for (uint32_t i = ; i < NUM_REGS; ++i) {
             // (1) If the current register is locked, it is not a candidate.
             if (m_data[i].lockCount)
                 continue;
@@ -120,18 +133,6 @@ public:
                 currentLowest = i;
             }
         }
-        // Loop over the remaining entries.
-        for (uint32_t i = 0; i <= m_lastAllocated; ++i) {
-            if (m_data[i].lockCount)
-                continue;
-            SpillHint spillOrder = m_data[i].spillOrder;
-            if (spillOrder == SpillHintInvalid)
-                return allocateInternal(i, spillMe);
-            if (spillOrder < currentSpillOrder) {
-                currentSpillOrder = spillOrder;
-                currentLowest = i;
-            }
-        }
 
         // Deadlock check - this could only occur is all registers are locked!
         ASSERT(currentLowest != NUM_REGS && currentSpillOrder != SpillHintInvalid);
@@ -139,6 +140,19 @@ public:
         return allocateInternal(currentLowest, spillMe);
     }
 
+    // Allocates the given register, even if this will force a spill.
+    VirtualRegister allocateSpecific(RegID reg)
+    {
+        unsigned index = BankInfo::toIndex(reg);
+
+        ++m_data[index].lockCount;
+        VirtualRegister name = nameAtIndex(index);
+        if (name.isValid())
+            releaseAtIndex(index);
+        
+        return name;
+    }
+
     // retain/release - these methods are used to associate/disassociate names
     // with values in registers. retain should only be called on locked registers.
     void retain(RegID reg, VirtualRegister name, SpillHint spillOrder)
@@ -151,8 +165,8 @@ public:
         ASSERT(index < NUM_REGS);
         ASSERT(m_data[index].lockCount);
         // 'index' should not currently be named, the new name must be valid.
-        ASSERT(m_data[index].name == InvalidVirtualRegister);
-        ASSERT(name != InvalidVirtualRegister);
+        ASSERT(!m_data[index].name.isValid());
+        ASSERT(name.isValid());
         // 'index' should not currently have a spillOrder.
         ASSERT(m_data[index].spillOrder == SpillHintInvalid);
 
@@ -187,25 +201,28 @@ public:
     }
 
     // Get the name (VirtualRegister) associated with the
-    // given register (or InvalidVirtualRegister for none).
+    // given register (or default VirtualRegister() for none).
     VirtualRegister name(RegID reg) const
     {
         return nameAtIndex(BankInfo::toIndex(reg));
     }
     
-#ifndef NDEBUG
+    bool isInUse(RegID reg) const
+    {
+        return isLocked(reg) || name(reg).isValid();
+    }
+    
     void dump()
     {
         // For each register, print the VirtualRegister 'name'.
         for (uint32_t i =0; i < NUM_REGS; ++i) {
-            if (m_data[i].name != InvalidVirtualRegister)
-                fprintf(stderr, "[%02d]", m_data[i].name);
+            if (m_data[i].name.isValid())
+                dataLogF("[%02d]", m_data[i].name.offset());
             else
-                fprintf(stderr, "[--]");
+                dataLogF("[--]");
         }
-        fprintf(stderr, "\n");
+        dataLogF("\n");
     }
-#endif
 
     class iterator {
     friend class RegisterBank<BankInfo>;
@@ -293,11 +310,11 @@ private:
         // 'index' must be a valid register.
         ASSERT(index < NUM_REGS);
         // 'index' should currently be named.
-        ASSERT(m_data[index].name != InvalidVirtualRegister);
+        ASSERT(m_data[index].name.isValid());
         // 'index' should currently have a valid spill order.
         ASSERT(m_data[index].spillOrder != SpillHintInvalid);
 
-        m_data[index].name = InvalidVirtualRegister;
+        m_data[index].name = VirtualRegister();
         m_data[index].spillOrder = SpillHintInvalid;
     }
 
@@ -308,7 +325,7 @@ private:
         ASSERT(i < NUM_REGS && !m_data[i].lockCount);
 
         // Return the VirtualRegister of the named value currently stored in
-        // the register being returned - or InvalidVirtualRegister if none.
+        // the register being returned - or default VirtualRegister() if none.
         spillMe = m_data[i].name;
 
         // Clear any name/spillOrder currently associated with the register,
@@ -316,7 +333,6 @@ private:
         // Mark the register as locked (with a lock count of 1).
         m_data[i].lockCount = 1;
 
-        m_lastAllocated = i;
         return BankInfo::toRegister(i);
     }
 
@@ -327,7 +343,7 @@ private:
     // count, name and spillOrder hint.
     struct MapEntry {
         MapEntry()
-            : name(InvalidVirtualRegister)
+            : name(VirtualRegister())
             , spillOrder(SpillHintInvalid)
             , lockCount(0)
         {
@@ -340,10 +356,11 @@ private:
 
     // Holds the current status of all registers.
     MapEntry m_data[NUM_REGS];
-    // Used to to implement a simple round-robin like allocation scheme.
-    uint32_t m_lastAllocated;
 };
 
+typedef RegisterBank<GPRInfo>::iterator gpr_iterator;
+typedef RegisterBank<FPRInfo>::iterator fpr_iterator;
+
 } } // namespace JSC::DFG
 
 #endif