#if ENABLE(DFG_JIT)
-#include <dfg/DFGNode.h>
+#include "DFGCommon.h"
+#include "FPRInfo.h"
+#include "GPRInfo.h"
namespace JSC { namespace DFG {
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
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.
// 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;
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);
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)
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);
}
// 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>;
// '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;
}
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,
// Mark the register as locked (with a lock count of 1).
m_data[i].lockCount = 1;
- m_lastAllocated = i;
return BankInfo::toRegister(i);
}
// count, name and spillOrder hint.
struct MapEntry {
MapEntry()
- : name(InvalidVirtualRegister)
+ : name(VirtualRegister())
, spillOrder(SpillHintInvalid)
, lockCount(0)
{
// 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