X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/14957cd040308e3eeec43d26bae5d76da13fcd85..refs/heads/master:/dfg/DFGRegisterBank.h?ds=sidebyside diff --git a/dfg/DFGRegisterBank.h b/dfg/DFGRegisterBank.h index f4fdd50..32c1e91 100644 --- a/dfg/DFGRegisterBank.h +++ b/dfg/DFGRegisterBank.h @@ -28,7 +28,9 @@ #if ENABLE(DFG_JIT) -#include +#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 = 0 ; 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; @@ -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::iterator gpr_iterator; +typedef RegisterBank::iterator fpr_iterator; + } } // namespace JSC::DFG #endif