| Index: src/register-allocator.h
|
| ===================================================================
|
| --- src/register-allocator.h (revision 2055)
|
| +++ src/register-allocator.h (working copy)
|
| @@ -30,6 +30,16 @@
|
|
|
| #include "macro-assembler.h"
|
|
|
| +#if V8_TARGET_ARCH_IA32
|
| +#include "ia32/register-allocator-ia32.h"
|
| +#elif V8_TARGET_ARCH_X64
|
| +#include "x64/register-allocator-x64.h"
|
| +#elif V8_TARGET_ARCH_ARM
|
| +#include "arm/register-allocator-arm.h"
|
| +#else
|
| +#error Unsupported target architecture.
|
| +#endif
|
| +
|
| namespace v8 {
|
| namespace internal {
|
|
|
| @@ -241,25 +251,28 @@
|
| }
|
| }
|
|
|
| - // Predicates and accessors for the reference counts. The versions
|
| - // that take a register code rather than a register are for
|
| - // convenience in loops over the register codes.
|
| - bool is_used(int reg_code) const { return ref_counts_[reg_code] > 0; }
|
| - bool is_used(Register reg) const { return is_used(reg.code()); }
|
| - int count(int reg_code) const { return ref_counts_[reg_code]; }
|
| - int count(Register reg) const { return count(reg.code()); }
|
| + // Predicates and accessors for the reference counts.
|
| + bool is_used(int num) {
|
| + ASSERT(0 <= num && num < kNumRegisters);
|
| + return ref_counts_[num] > 0;
|
| + }
|
|
|
| + int count(int num) {
|
| + ASSERT(0 <= num && num < kNumRegisters);
|
| + return ref_counts_[num];
|
| + }
|
| +
|
| // Record a use of a register by incrementing its reference count.
|
| - void Use(Register reg) {
|
| - ref_counts_[reg.code()]++;
|
| + void Use(int num) {
|
| + ASSERT(0 <= num && num < kNumRegisters);
|
| + ref_counts_[num]++;
|
| }
|
|
|
| // Record that a register will no longer be used by decrementing its
|
| // reference count.
|
| - void Unuse(Register reg) {
|
| - ASSERT(!reg.is(no_reg));
|
| - ASSERT(is_used(reg.code()));
|
| - ref_counts_[reg.code()]--;
|
| + void Unuse(int num) {
|
| + ASSERT(is_used(num));
|
| + ref_counts_[num]--;
|
| }
|
|
|
| // Copy the reference counts from this register file to the other.
|
| @@ -270,17 +283,18 @@
|
| }
|
|
|
| private:
|
| + static const int kNumRegisters = RegisterAllocatorConstants::kNumRegisters;
|
| +
|
| int ref_counts_[kNumRegisters];
|
|
|
| - // Very fast inlined loop to find a free register.
|
| - // Used in RegisterAllocator::AllocateWithoutSpilling.
|
| - // Returns kNumRegisters if no free register found.
|
| - inline int ScanForFreeRegister() {
|
| - int i = 0;
|
| - for (; i < kNumRegisters ; ++i) {
|
| - if (ref_counts_[i] == 0) break;
|
| + // Very fast inlined loop to find a free register. Used in
|
| + // RegisterAllocator::AllocateWithoutSpilling. Returns
|
| + // kInvalidRegister if no free register found.
|
| + int ScanForFreeRegister() {
|
| + for (int i = 0; i < RegisterAllocatorConstants::kNumRegisters; i++) {
|
| + if (!is_used(i)) return i;
|
| }
|
| - return i;
|
| + return RegisterAllocatorConstants::kInvalidRegister;
|
| }
|
|
|
| friend class RegisterAllocator;
|
| @@ -293,55 +307,62 @@
|
|
|
| class RegisterAllocator BASE_EMBEDDED {
|
| public:
|
| + static const int kNumRegisters =
|
| + RegisterAllocatorConstants::kNumRegisters;
|
| + static const int kInvalidRegister =
|
| + RegisterAllocatorConstants::kInvalidRegister;
|
| +
|
| explicit RegisterAllocator(CodeGenerator* cgen) : cgen_(cgen) {}
|
|
|
| - // A register file with each of the reserved registers counted once.
|
| - static RegisterFile Reserved();
|
| + // True if the register is reserved by the code generator, false if it
|
| + // can be freely used by the allocator Defined in the
|
| + // platform-specific XXX-inl.h files..
|
| + static inline bool IsReserved(Register reg);
|
|
|
| - // Unuse all the reserved registers in a register file.
|
| - static void UnuseReserved(RegisterFile* register_file);
|
| + // Convert between (unreserved) assembler registers and allocator
|
| + // numbers. Defined in the platform-specific XXX-inl.h files.
|
| + static inline int ToNumber(Register reg);
|
| + static inline Register ToRegister(int num);
|
|
|
| - // True if the register is reserved by the code generator, false if it
|
| - // can be freely used by the allocator.
|
| - static bool IsReserved(int reg_code);
|
| - static bool IsReserved(Register reg) { return IsReserved(reg); }
|
| -
|
| // Predicates and accessors for the registers' reference counts.
|
| - bool is_used(int reg_code) const { return registers_.is_used(reg_code); }
|
| - bool is_used(Register reg) const { return registers_.is_used(reg.code()); }
|
| - int count(int reg_code) const { return registers_.count(reg_code); }
|
| - int count(Register reg) const { return registers_.count(reg.code()); }
|
| + bool is_used(int num) { return registers_.is_used(num); }
|
| + bool is_used(Register reg) { return registers_.is_used(ToNumber(reg)); }
|
|
|
| + int count(int num) { return registers_.count(num); }
|
| + int count(Register reg) { return registers_.count(ToNumber(reg)); }
|
| +
|
| // Explicitly record a reference to a register.
|
| - void Use(Register reg) { registers_.Use(reg); }
|
| + void Use(int num) { registers_.Use(num); }
|
| + void Use(Register reg) { registers_.Use(ToNumber(reg)); }
|
|
|
| // Explicitly record that a register will no longer be used.
|
| - void Unuse(Register reg) { registers_.Unuse(reg); }
|
| + void Unuse(int num) { registers_.Unuse(num); }
|
| + void Unuse(Register reg) { registers_.Unuse(ToNumber(reg)); }
|
|
|
| + // Reset the register reference counts to free all non-reserved registers.
|
| + void Reset() { registers_.Reset(); }
|
| +
|
| // Initialize the register allocator for entry to a JS function. On
|
| - // entry, the registers used by the JS calling convention are
|
| - // externally referenced (ie, outside the virtual frame); and the
|
| - // other registers are free.
|
| - void Initialize();
|
| + // entry, the (non-reserved) registers used by the JS calling
|
| + // convention are referenced and the other (non-reserved) registers
|
| + // are free.
|
| + inline void Initialize();
|
|
|
| - // Reset the register reference counts to free all non-reserved registers.
|
| - // A frame-external reference is kept to each of the reserved registers.
|
| - void Reset();
|
| -
|
| // Allocate a free register and return a register result if possible or
|
| // fail and return an invalid result.
|
| Result Allocate();
|
|
|
| - // Allocate a specific register if possible, spilling it from the frame if
|
| - // necessary, or else fail and return an invalid result.
|
| + // Allocate a specific register if possible, spilling it from the
|
| + // current frame if necessary, or else fail and return an invalid
|
| + // result.
|
| Result Allocate(Register target);
|
|
|
| - // Allocate a free register without spilling any from the current frame or
|
| - // fail and return an invalid result.
|
| + // Allocate a free register without spilling any from the current
|
| + // frame or fail and return an invalid result.
|
| Result AllocateWithoutSpilling();
|
|
|
| - // Allocate a free byte register without spilling any from the
|
| - // current frame or fail and return an invalid result.
|
| + // Allocate a free byte register without spilling any from the current
|
| + // frame or fail and return an invalid result.
|
| Result AllocateByteRegisterWithoutSpilling();
|
|
|
| // Copy the internal state to a register file, to be restored later by
|
| @@ -350,6 +371,7 @@
|
| registers_.CopyTo(register_file);
|
| }
|
|
|
| + // Restore the internal state.
|
| void RestoreFrom(RegisterFile* register_file) {
|
| register_file->CopyTo(®isters_);
|
| }
|
|
|