Remove register index/code indirection
authordanno <danno@chromium.org>
Thu, 24 Sep 2015 12:52:54 +0000 (05:52 -0700)
committerCommit bot <commit-bot@chromium.org>
Thu, 24 Sep 2015 12:53:13 +0000 (12:53 +0000)
Previous to this patch, both the lithium and TurboFan register
allocators tracked allocated registers by "indices", rather than
the register codes used elsewhere in the runtime. This patch
ensures that codes are used everywhere, and in the process cleans
up a bunch of redundant code and adds more structure to how the
set of allocatable registers is defined.

Some highlights of changes:

* TurboFan's RegisterConfiguration class moved to V8's top level
  so that it can be shared with Crankshaft.
* Various "ToAllocationIndex" and related methods removed.
* Code that can be easily shared between Register classes on
  different platforms is now shared.
* The list of allocatable registers on each platform is declared
  as a list rather than implicitly via the register index <->
  code mapping.

Review URL: https://codereview.chromium.org/1287383003

Cr-Commit-Position: refs/heads/master@{#30913}

93 files changed:
BUILD.gn
src/arm/assembler-arm-inl.h
src/arm/assembler-arm.cc
src/arm/assembler-arm.h
src/arm/constants-arm.cc
src/arm/deoptimizer-arm.cc
src/arm/disasm-arm.cc
src/arm/lithium-arm.cc
src/arm/lithium-codegen-arm.cc
src/arm/macro-assembler-arm.cc
src/arm/macro-assembler-arm.h
src/arm/simulator-arm.cc
src/arm64/assembler-arm64.cc
src/arm64/assembler-arm64.h
src/arm64/constants-arm64.h
src/arm64/deoptimizer-arm64.cc
src/arm64/lithium-arm64.cc
src/arm64/lithium-codegen-arm64.cc
src/arm64/macro-assembler-arm64.cc
src/arm64/simulator-arm64.h
src/arm64/utils-arm64.h
src/assembler.cc
src/assembler.h
src/compiler/c-linkage.cc
src/compiler/code-generator-impl.h
src/compiler/code-generator.cc
src/compiler/graph-visualizer.cc
src/compiler/instruction-selector-impl.h
src/compiler/instruction.cc
src/compiler/instruction.h
src/compiler/linkage.cc
src/compiler/pipeline.cc
src/compiler/pipeline.h
src/compiler/register-allocator-verifier.cc
src/compiler/register-allocator.cc
src/compiler/register-allocator.h
src/compiler/register-configuration.cc [deleted file]
src/compiler/register-configuration.h [deleted file]
src/deoptimizer.cc
src/frames.cc
src/hydrogen.cc
src/ia32/assembler-ia32.h
src/ia32/code-stubs-ia32.h
src/ia32/deoptimizer-ia32.cc
src/ia32/lithium-codegen-ia32.cc
src/ia32/lithium-gap-resolver-ia32.cc
src/ia32/lithium-gap-resolver-ia32.h
src/ia32/lithium-ia32.cc
src/ia32/macro-assembler-ia32.h
src/lithium-allocator.cc
src/lithium-allocator.h
src/lithium.cc
src/mips/assembler-mips-inl.h
src/mips/assembler-mips.cc
src/mips/assembler-mips.h
src/mips/deoptimizer-mips.cc
src/mips/lithium-codegen-mips.cc
src/mips/lithium-mips.cc
src/mips/macro-assembler-mips.cc
src/mips/macro-assembler-mips.h
src/mips64/assembler-mips64-inl.h
src/mips64/assembler-mips64.cc
src/mips64/assembler-mips64.h
src/mips64/deoptimizer-mips64.cc
src/mips64/lithium-codegen-mips64.cc
src/mips64/lithium-mips64.cc
src/mips64/macro-assembler-mips64.cc
src/mips64/macro-assembler-mips64.h
src/objects.cc
src/register-configuration.cc [new file with mode: 0644]
src/register-configuration.h [new file with mode: 0644]
src/x64/assembler-x64.cc
src/x64/assembler-x64.h
src/x64/code-stubs-x64.h
src/x64/deoptimizer-x64.cc
src/x64/lithium-codegen-x64.cc
src/x64/lithium-x64.cc
src/x64/macro-assembler-x64.cc
src/x64/macro-assembler-x64.h
src/x87/assembler-x87.h
test/cctest/compiler/test-gap-resolver.cc
test/cctest/compiler/test-run-native-calls.cc
test/cctest/test-code-stubs-arm.cc
test/cctest/test-code-stubs-arm64.cc
test/cctest/test-code-stubs-ia32.cc
test/cctest/test-code-stubs-mips.cc
test/cctest/test-code-stubs-mips64.cc
test/cctest/test-code-stubs-x64.cc
test/unittests/compiler/instruction-selector-unittest.cc
test/unittests/compiler/instruction-sequence-unittest.cc
test/unittests/compiler/instruction-sequence-unittest.h
test/unittests/compiler/register-allocator-unittest.cc
tools/gyp/v8.gyp

index a67948be1fd44aa53c1e149243469b9fc66546ea..90b8fe237ced05720689aa690354485db10a5edc 100644 (file)
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -823,8 +823,6 @@ source_set("v8_base") {
     "src/compiler/register-allocator.h",
     "src/compiler/register-allocator-verifier.cc",
     "src/compiler/register-allocator-verifier.h",
-    "src/compiler/register-configuration.cc",
-    "src/compiler/register-configuration.h",
     "src/compiler/representation-change.h",
     "src/compiler/schedule.cc",
     "src/compiler/schedule.h",
@@ -1139,6 +1137,8 @@ source_set("v8_base") {
     "src/regexp/regexp-macro-assembler.h",
     "src/regexp/regexp-stack.cc",
     "src/regexp/regexp-stack.h",
+    "src/register-configuration.cc",
+    "src/register-configuration.h",
     "src/runtime-profiler.cc",
     "src/runtime-profiler.h",
     "src/runtime/runtime-array.cc",
index 8f8956c9e1c7eb25890726abb3cfd3addeceeb54..0037e30ddac1b1467ce5bbc0b0cb8d6c1b03afd2 100644 (file)
@@ -50,53 +50,11 @@ namespace internal {
 bool CpuFeatures::SupportsCrankshaft() { return IsSupported(VFP3); }
 
 
-int Register::NumAllocatableRegisters() {
-  return kMaxNumAllocatableRegisters;
-}
-
-
-int DwVfpRegister::NumRegisters() {
+int DoubleRegister::NumRegisters() {
   return CpuFeatures::IsSupported(VFP32DREGS) ? 32 : 16;
 }
 
 
-int DwVfpRegister::NumReservedRegisters() {
-  return kNumReservedRegisters;
-}
-
-
-int DwVfpRegister::NumAllocatableRegisters() {
-  return NumRegisters() - kNumReservedRegisters;
-}
-
-
-// static
-int DwVfpRegister::NumAllocatableAliasedRegisters() {
-  return LowDwVfpRegister::kMaxNumLowRegisters - kNumReservedRegisters;
-}
-
-
-int DwVfpRegister::ToAllocationIndex(DwVfpRegister reg) {
-  DCHECK(!reg.is(kDoubleRegZero));
-  DCHECK(!reg.is(kScratchDoubleReg));
-  if (reg.code() > kDoubleRegZero.code()) {
-    return reg.code() - kNumReservedRegisters;
-  }
-  return reg.code();
-}
-
-
-DwVfpRegister DwVfpRegister::FromAllocationIndex(int index) {
-  DCHECK(index >= 0 && index < NumAllocatableRegisters());
-  DCHECK(kScratchDoubleReg.code() - kDoubleRegZero.code() ==
-         kNumReservedRegisters - 1);
-  if (index >= kDoubleRegZero.code()) {
-    return from_code(index + kNumReservedRegisters);
-  }
-  return from_code(index);
-}
-
-
 void RelocInfo::apply(intptr_t delta) {
   if (RelocInfo::IsInternalReference(rmode_)) {
     // absolute code pointer inside code object moves with the code object.
index b5910d05be5de63c9092aedecdec05ec9e487239..32d36a27f2e6764245de1c273556997d9159feaf 100644 (file)
@@ -213,18 +213,6 @@ void CpuFeatures::PrintFeatures() {
 }
 
 
-// -----------------------------------------------------------------------------
-// Implementation of DwVfpRegister
-
-const char* DwVfpRegister::AllocationIndexToString(int index) {
-  DCHECK(index >= 0 && index < NumAllocatableRegisters());
-  DCHECK(kScratchDoubleReg.code() - kDoubleRegZero.code() ==
-         kNumReservedRegisters - 1);
-  if (index >= kDoubleRegZero.code()) index += kNumReservedRegisters;
-  return VFPRegisters::Name(index, true);
-}
-
-
 // -----------------------------------------------------------------------------
 // Implementation of RelocInfo
 
@@ -391,26 +379,26 @@ NeonListOperand::NeonListOperand(DoubleRegister base, int registers_count) {
 // str(r, MemOperand(sp, 4, NegPreIndex), al) instruction (aka push(r))
 // register r is not encoded.
 const Instr kPushRegPattern =
-    al | B26 | 4 | NegPreIndex | kRegister_sp_Code * B16;
+    al | B26 | 4 | NegPreIndex | Register::kCode_sp * B16;
 // ldr(r, MemOperand(sp, 4, PostIndex), al) instruction (aka pop(r))
 // register r is not encoded.
 const Instr kPopRegPattern =
-    al | B26 | L | 4 | PostIndex | kRegister_sp_Code * B16;
+    al | B26 | L | 4 | PostIndex | Register::kCode_sp * B16;
 // ldr rd, [pc, #offset]
 const Instr kLdrPCImmedMask = 15 * B24 | 7 * B20 | 15 * B16;
-const Instr kLdrPCImmedPattern = 5 * B24 | L | kRegister_pc_Code * B16;
+const Instr kLdrPCImmedPattern = 5 * B24 | L | Register::kCode_pc * B16;
 // ldr rd, [pp, #offset]
 const Instr kLdrPpImmedMask = 15 * B24 | 7 * B20 | 15 * B16;
-const Instr kLdrPpImmedPattern = 5 * B24 | L | kRegister_r8_Code * B16;
+const Instr kLdrPpImmedPattern = 5 * B24 | L | Register::kCode_r8 * B16;
 // ldr rd, [pp, rn]
 const Instr kLdrPpRegMask = 15 * B24 | 7 * B20 | 15 * B16;
-const Instr kLdrPpRegPattern = 7 * B24 | L | kRegister_r8_Code * B16;
+const Instr kLdrPpRegPattern = 7 * B24 | L | Register::kCode_r8 * B16;
 // vldr dd, [pc, #offset]
 const Instr kVldrDPCMask = 15 * B24 | 3 * B20 | 15 * B16 | 15 * B8;
-const Instr kVldrDPCPattern = 13 * B24 | L | kRegister_pc_Code * B16 | 11 * B8;
+const Instr kVldrDPCPattern = 13 * B24 | L | Register::kCode_pc * B16 | 11 * B8;
 // vldr dd, [pp, #offset]
 const Instr kVldrDPpMask = 15 * B24 | 3 * B20 | 15 * B16 | 15 * B8;
-const Instr kVldrDPpPattern = 13 * B24 | L | kRegister_r8_Code * B16 | 11 * B8;
+const Instr kVldrDPpPattern = 13 * B24 | L | Register::kCode_r8 * B16 | 11 * B8;
 // blxcc rm
 const Instr kBlxRegMask =
     15 * B24 | 15 * B20 | 15 * B16 | 15 * B12 | 15 * B8 | 15 * B4;
@@ -437,13 +425,13 @@ const Instr kAndBicFlip = 0xe * B21;
 
 // A mask for the Rd register for push, pop, ldr, str instructions.
 const Instr kLdrRegFpOffsetPattern =
-    al | B26 | L | Offset | kRegister_fp_Code * B16;
+    al | B26 | L | Offset | Register::kCode_fp * B16;
 const Instr kStrRegFpOffsetPattern =
-    al | B26 | Offset | kRegister_fp_Code * B16;
+    al | B26 | Offset | Register::kCode_fp * B16;
 const Instr kLdrRegFpNegOffsetPattern =
-    al | B26 | L | NegOffset | kRegister_fp_Code * B16;
+    al | B26 | L | NegOffset | Register::kCode_fp * B16;
 const Instr kStrRegFpNegOffsetPattern =
-    al | B26 | NegOffset | kRegister_fp_Code * B16;
+    al | B26 | NegOffset | Register::kCode_fp * B16;
 const Instr kLdrStrInstrTypeMask = 0xffff0000;
 
 
@@ -619,21 +607,21 @@ Instr Assembler::SetAddRegisterImmediateOffset(Instr instr, int offset) {
 
 Register Assembler::GetRd(Instr instr) {
   Register reg;
-  reg.code_ = Instruction::RdValue(instr);
+  reg.reg_code = Instruction::RdValue(instr);
   return reg;
 }
 
 
 Register Assembler::GetRn(Instr instr) {
   Register reg;
-  reg.code_ = Instruction::RnValue(instr);
+  reg.reg_code = Instruction::RnValue(instr);
   return reg;
 }
 
 
 Register Assembler::GetRm(Instr instr) {
   Register reg;
-  reg.code_ = Instruction::RmValue(instr);
+  reg.reg_code = Instruction::RmValue(instr);
   return reg;
 }
 
index c54e51df78cb57c146f1f9f815214ca899057e49..aa13a828461d5fbc05994eacc4c61003a95c723e 100644 (file)
 namespace v8 {
 namespace internal {
 
+// clang-format off
+#define GENERAL_REGISTERS(V)                              \
+  V(r0)  V(r1)  V(r2)  V(r3)  V(r4)  V(r5)  V(r6)  V(r7)  \
+  V(r8)  V(r9)  V(r10) V(fp)  V(ip)  V(sp)  V(lr)  V(pc)
+
+#define ALLOCATABLE_GENERAL_REGISTERS(V) \
+  V(r0)  V(r1)  V(r2)  V(r3)  V(r4)  V(r5)  V(r6)  V(r7)  V(r8)
+
+#define DOUBLE_REGISTERS(V)                               \
+  V(d0)  V(d1)  V(d2)  V(d3)  V(d4)  V(d5)  V(d6)  V(d7)  \
+  V(d8)  V(d9)  V(d10) V(d11) V(d12) V(d13) V(d14) V(d15) \
+  V(d16) V(d17) V(d18) V(d19) V(d20) V(d21) V(d22) V(d23) \
+  V(d24) V(d25) V(d26) V(d27) V(d28) V(d29) V(d30) V(d31)
+
+#define ALLOCATABLE_DOUBLE_REGISTERS(V)                   \
+  V(d0)  V(d1)  V(d2)  V(d3)  V(d4)  V(d5)  V(d6)  V(d7)  \
+  V(d8)  V(d9)  V(d10) V(d11) V(d12) V(d13)               \
+  V(d16) V(d17) V(d18) V(d19) V(d20) V(d21) V(d22) V(d23) \
+  V(d24) V(d25) V(d26) V(d27) V(d28) V(d29) V(d30) V(d31)
+
+#define ALLOCATABLE_NO_VFP32_DOUBLE_REGISTERS(V)          \
+  V(d0)  V(d1)  V(d2)  V(d3)  V(d4)  V(d5)  V(d6)  V(d7)  \
+  V(d8)  V(d9)  V(d10) V(d11) V(d12) V(d13)               \
+// clang-format on
+
 // CPU Registers.
 //
 // 1) We would prefer to use an enum, but enum values are assignment-
@@ -71,190 +96,123 @@ namespace internal {
 // mode. This way we get the compile-time error checking in debug mode
 // and best performance in optimized code.
 
-// These constants are used in several locations, including static initializers
-const int kRegister_no_reg_Code = -1;
-const int kRegister_r0_Code = 0;
-const int kRegister_r1_Code = 1;
-const int kRegister_r2_Code = 2;
-const int kRegister_r3_Code = 3;
-const int kRegister_r4_Code = 4;
-const int kRegister_r5_Code = 5;
-const int kRegister_r6_Code = 6;
-const int kRegister_r7_Code = 7;
-const int kRegister_r8_Code = 8;
-const int kRegister_r9_Code = 9;
-const int kRegister_r10_Code = 10;
-const int kRegister_fp_Code = 11;
-const int kRegister_ip_Code = 12;
-const int kRegister_sp_Code = 13;
-const int kRegister_lr_Code = 14;
-const int kRegister_pc_Code = 15;
-
-// Core register
 struct Register {
-  static const int kNumRegisters = 16;
-  static const int kMaxNumAllocatableRegisters =
-      FLAG_enable_embedded_constant_pool ? 8 : 9;
-  static const int kSizeInBytes = 4;
-
-  inline static int NumAllocatableRegisters();
-
-  static int ToAllocationIndex(Register reg) {
-    DCHECK(reg.code() < kMaxNumAllocatableRegisters);
-    return reg.code();
-  }
+  enum Code {
+#define REGISTER_CODE(R) kCode_##R,
+    GENERAL_REGISTERS(REGISTER_CODE)
+#undef REGISTER_CODE
+        kAfterLast,
+    kCode_no_reg = -1
+  };
 
-  static Register FromAllocationIndex(int index) {
-    DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
-    return from_code(index);
-  }
-
-  static const char* AllocationIndexToString(int index) {
-    DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
-    const char* const names[] = {
-      "r0",
-      "r1",
-      "r2",
-      "r3",
-      "r4",
-      "r5",
-      "r6",
-      "r7",
-      "r8",
-    };
-    if (FLAG_enable_embedded_constant_pool && (index >= 7)) {
-      return names[index + 1];
-    }
-    return names[index];
-  }
+  static const int kNumRegisters = Code::kAfterLast;
 
   static Register from_code(int code) {
-    Register r = { code };
+    DCHECK(code >= 0);
+    DCHECK(code < kNumRegisters);
+    Register r = {code};
     return r;
   }
-
-  bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
-  bool is(Register reg) const { return code_ == reg.code_; }
+  const char* ToString();
+  bool IsAllocatable() const;
+  bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; }
+  bool is(Register reg) const { return reg_code == reg.reg_code; }
   int code() const {
     DCHECK(is_valid());
-    return code_;
+    return reg_code;
   }
   int bit() const {
     DCHECK(is_valid());
-    return 1 << code_;
+    return 1 << reg_code;
   }
-
   void set_code(int code) {
-    code_ = code;
+    reg_code = code;
     DCHECK(is_valid());
   }
 
   // Unfortunately we can't make this private in a struct.
-  int code_;
+  int reg_code;
 };
 
-const Register no_reg = { kRegister_no_reg_Code };
-
-const Register r0  = { kRegister_r0_Code };
-const Register r1  = { kRegister_r1_Code };
-const Register r2  = { kRegister_r2_Code };
-const Register r3  = { kRegister_r3_Code };
-const Register r4  = { kRegister_r4_Code };
-const Register r5  = { kRegister_r5_Code };
-const Register r6  = { kRegister_r6_Code };
-// Used as context register.
-const Register r7 = {kRegister_r7_Code};
-// Used as constant pool pointer register if FLAG_enable_embedded_constant_pool.
-const Register r8  = { kRegister_r8_Code };
-// Used as lithium codegen scratch register.
-const Register r9  = { kRegister_r9_Code };
-// Used as roots register.
-const Register r10 = { kRegister_r10_Code };
-const Register fp  = { kRegister_fp_Code };
-const Register ip  = { kRegister_ip_Code };
-const Register sp  = { kRegister_sp_Code };
-const Register lr  = { kRegister_lr_Code };
-const Register pc  = { kRegister_pc_Code };
+// r7: context register
+// r8: constant pool pointer register if FLAG_enable_embedded_constant_pool.
+// r9: lithium scratch
+#define DECLARE_REGISTER(R) const Register R = {Register::kCode_##R};
+GENERAL_REGISTERS(DECLARE_REGISTER)
+#undef DECLARE_REGISTER
+const Register no_reg = {Register::kCode_no_reg};
 
 // Single word VFP register.
 struct SwVfpRegister {
   static const int kSizeInBytes = 4;
-  bool is_valid() const { return 0 <= code_ && code_ < 32; }
-  bool is(SwVfpRegister reg) const { return code_ == reg.code_; }
+  bool is_valid() const { return 0 <= reg_code && reg_code < 32; }
+  bool is(SwVfpRegister reg) const { return reg_code == reg.reg_code; }
   int code() const {
     DCHECK(is_valid());
-    return code_;
+    return reg_code;
   }
   int bit() const {
     DCHECK(is_valid());
-    return 1 << code_;
+    return 1 << reg_code;
   }
   void split_code(int* vm, int* m) const {
     DCHECK(is_valid());
-    *m = code_ & 0x1;
-    *vm = code_ >> 1;
+    *m = reg_code & 0x1;
+    *vm = reg_code >> 1;
   }
 
-  int code_;
+  int reg_code;
 };
 
 
 // Double word VFP register.
-struct DwVfpRegister {
-  static const int kMaxNumRegisters = 32;
+struct DoubleRegister {
+  enum Code {
+#define REGISTER_CODE(R) kCode_##R,
+    DOUBLE_REGISTERS(REGISTER_CODE)
+#undef REGISTER_CODE
+        kAfterLast,
+    kCode_no_reg = -1
+  };
+
+  static const int kMaxNumRegisters = Code::kAfterLast;
+
+  inline static int NumRegisters();
+
   // A few double registers are reserved: one as a scratch register and one to
   // hold 0.0, that does not fit in the immediate field of vmov instructions.
   //  d14: 0.0
   //  d15: scratch register.
-  static const int kNumReservedRegisters = 2;
-  static const int kMaxNumAllocatableRegisters = kMaxNumRegisters -
-      kNumReservedRegisters;
   static const int kSizeInBytes = 8;
 
-  // Note: the number of registers can be different at snapshot and run-time.
-  // Any code included in the snapshot must be able to run both with 16 or 32
-  // registers.
-  inline static int NumRegisters();
-  inline static int NumReservedRegisters();
-  inline static int NumAllocatableRegisters();
-
-  // TODO(turbofan): This is a temporary work-around required because our
-  // register allocator does not yet support the aliasing of single/double
-  // registers on ARM.
-  inline static int NumAllocatableAliasedRegisters();
-
-  inline static int ToAllocationIndex(DwVfpRegister reg);
-  static const char* AllocationIndexToString(int index);
-  inline static DwVfpRegister FromAllocationIndex(int index);
-
-  static DwVfpRegister from_code(int code) {
-    DwVfpRegister r = { code };
-    return r;
-  }
-
-  bool is_valid() const {
-    return 0 <= code_ && code_ < kMaxNumRegisters;
-  }
-  bool is(DwVfpRegister reg) const { return code_ == reg.code_; }
+  const char* ToString();
+  bool IsAllocatable() const;
+  bool is_valid() const { return 0 <= reg_code && reg_code < kMaxNumRegisters; }
+  bool is(DoubleRegister reg) const { return reg_code == reg.reg_code; }
   int code() const {
     DCHECK(is_valid());
-    return code_;
+    return reg_code;
   }
   int bit() const {
     DCHECK(is_valid());
-    return 1 << code_;
+    return 1 << reg_code;
+  }
+
+  static DoubleRegister from_code(int code) {
+    DoubleRegister r = {code};
+    return r;
   }
   void split_code(int* vm, int* m) const {
     DCHECK(is_valid());
-    *m = (code_ & 0x10) >> 4;
-    *vm = code_ & 0x0F;
+    *m = (reg_code & 0x10) >> 4;
+    *vm = reg_code & 0x0F;
   }
 
-  int code_;
+  int reg_code;
 };
 
 
-typedef DwVfpRegister DoubleRegister;
+typedef DoubleRegister DwVfpRegister;
 
 
 // Double word VFP register d0-15.
@@ -262,7 +220,7 @@ struct LowDwVfpRegister {
  public:
   static const int kMaxNumLowRegisters = 16;
   operator DwVfpRegister() const {
-    DwVfpRegister r = { code_ };
+    DwVfpRegister r = { reg_code };
     return r;
   }
   static LowDwVfpRegister from_code(int code) {
@@ -271,30 +229,30 @@ struct LowDwVfpRegister {
   }
 
   bool is_valid() const {
-    return 0 <= code_ && code_ < kMaxNumLowRegisters;
+    return 0 <= reg_code && reg_code < kMaxNumLowRegisters;
   }
-  bool is(DwVfpRegister reg) const { return code_ == reg.code_; }
-  bool is(LowDwVfpRegister reg) const { return code_ == reg.code_; }
+  bool is(DwVfpRegister reg) const { return reg_code == reg.reg_code; }
+  bool is(LowDwVfpRegister reg) const { return reg_code == reg.reg_code; }
   int code() const {
     DCHECK(is_valid());
-    return code_;
+    return reg_code;
   }
   SwVfpRegister low() const {
     SwVfpRegister reg;
-    reg.code_ = code_ * 2;
+    reg.reg_code = reg_code * 2;
 
     DCHECK(reg.is_valid());
     return reg;
   }
   SwVfpRegister high() const {
     SwVfpRegister reg;
-    reg.code_ = (code_ * 2) + 1;
+    reg.reg_code = (reg_code * 2) + 1;
 
     DCHECK(reg.is_valid());
     return reg;
   }
 
-  int code_;
+  int reg_code;
 };
 
 
@@ -308,21 +266,21 @@ struct QwNeonRegister {
   }
 
   bool is_valid() const {
-    return (0 <= code_) && (code_ < kMaxNumRegisters);
+    return (0 <= reg_code) && (reg_code < kMaxNumRegisters);
   }
-  bool is(QwNeonRegister reg) const { return code_ == reg.code_; }
+  bool is(QwNeonRegister reg) const { return reg_code == reg.reg_code; }
   int code() const {
     DCHECK(is_valid());
-    return code_;
+    return reg_code;
   }
   void split_code(int* vm, int* m) const {
     DCHECK(is_valid());
-    int encoded_code = code_ << 1;
+    int encoded_code = reg_code << 1;
     *m = (encoded_code & 0x10) >> 4;
     *vm = encoded_code & 0x0F;
   }
 
-  int code_;
+  int reg_code;
 };
 
 
@@ -427,19 +385,19 @@ const QwNeonRegister q15 = { 15 };
 
 // Coprocessor register
 struct CRegister {
-  bool is_valid() const { return 0 <= code_ && code_ < 16; }
-  bool is(CRegister creg) const { return code_ == creg.code_; }
+  bool is_valid() const { return 0 <= reg_code && reg_code < 16; }
+  bool is(CRegister creg) const { return reg_code == creg.reg_code; }
   int code() const {
     DCHECK(is_valid());
-    return code_;
+    return reg_code;
   }
   int bit() const {
     DCHECK(is_valid());
-    return 1 << code_;
+    return 1 << reg_code;
   }
 
   // Unfortunately we can't make this private in a struct.
-  int code_;
+  int reg_code;
 };
 
 
index 9fefc3140a999429d0a1853bf75ae08ce59224ca..915d9030e8922a6f8c4e433a1936b692540d5090 100644 (file)
@@ -51,17 +51,6 @@ const Registers::RegisterAlias Registers::aliases_[] = {
 };
 
 
-const char* Registers::Name(int reg) {
-  const char* result;
-  if ((0 <= reg) && (reg < kNumRegisters)) {
-    result = names_[reg];
-  } else {
-    result = "noreg";
-  }
-  return result;
-}
-
-
 // Support for VFP registers s0 to s31 (d0 to d15) and d16-d31.
 // Note that "sN:sM" is the same as "dN/2" up to d15.
 // These register names are defined in a way to match the native disassembler
index 312bb00df3243ba54788b65927c66554cf6c8abc..91faa28bc7dfdf07f12a40897aaf2e3092aa7622 100644 (file)
@@ -5,6 +5,7 @@
 #include "src/codegen.h"
 #include "src/deoptimizer.h"
 #include "src/full-codegen/full-codegen.h"
+#include "src/register-configuration.h"
 #include "src/safepoint-table.h"
 
 namespace v8 {
@@ -93,7 +94,7 @@ void Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) {
   }
   input_->SetRegister(sp.code(), reinterpret_cast<intptr_t>(frame->sp()));
   input_->SetRegister(fp.code(), reinterpret_cast<intptr_t>(frame->fp()));
-  for (int i = 0; i < DoubleRegister::NumAllocatableRegisters(); i++) {
+  for (int i = 0; i < DoubleRegister::kMaxNumRegisters; i++) {
     input_->SetDoubleRegister(i, 0.0);
   }
 
@@ -142,8 +143,7 @@ void Deoptimizer::TableEntryGenerator::Generate() {
   // Everything but pc, lr and ip which will be saved but not restored.
   RegList restored_regs = kJSCallerSaved | kCalleeSaved | ip.bit();
 
-  const int kDoubleRegsSize =
-      kDoubleSize * DwVfpRegister::kMaxNumAllocatableRegisters;
+  const int kDoubleRegsSize = kDoubleSize * DwVfpRegister::kMaxNumRegisters;
 
   // Save all allocatable VFP registers before messing with them.
   DCHECK(kDoubleRegZero.code() == 14);
@@ -152,11 +152,11 @@ void Deoptimizer::TableEntryGenerator::Generate() {
   // Check CPU flags for number of registers, setting the Z condition flag.
   __ CheckFor32DRegs(ip);
 
-  // Push registers d0-d13, and possibly d16-d31, on the stack.
+  // Push registers d0-d15, and possibly d16-d31, on the stack.
   // If d16-d31 are not pushed, decrease the stack pointer instead.
   __ vstm(db_w, sp, d16, d31, ne);
   __ sub(sp, sp, Operand(16 * kDoubleSize), LeaveCC, eq);
-  __ vstm(db_w, sp, d0, d13);
+  __ vstm(db_w, sp, d0, d15);
 
   // Push all 16 registers (needed to populate FrameDescription::registers_).
   // TODO(1588) Note that using pc with stm is deprecated, so we should perhaps
@@ -211,9 +211,11 @@ void Deoptimizer::TableEntryGenerator::Generate() {
   // Copy VFP registers to
   // double_registers_[DoubleRegister::kMaxNumAllocatableRegisters]
   int double_regs_offset = FrameDescription::double_registers_offset();
-  for (int i = 0; i < DwVfpRegister::kMaxNumAllocatableRegisters; ++i) {
-    int dst_offset = i * kDoubleSize + double_regs_offset;
-    int src_offset = i * kDoubleSize + kNumberOfRegisters * kPointerSize;
+  const RegisterConfiguration* config = RegisterConfiguration::ArchDefault();
+  for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
+    int code = config->GetAllocatableDoubleCode(i);
+    int dst_offset = code * kDoubleSize + double_regs_offset;
+    int src_offset = code * kDoubleSize + kNumberOfRegisters * kPointerSize;
     __ vldr(d0, sp, src_offset);
     __ vstr(d0, r1, dst_offset);
   }
index 0cc24e00af0b8e87c15568edb7a6a0d8d16eee7f..9d86579f288ccb313881b83c5cebfb9b4beda316 100644 (file)
@@ -1923,7 +1923,7 @@ const char* NameConverter::NameOfConstant(byte* addr) const {
 
 
 const char* NameConverter::NameOfCPURegister(int reg) const {
-  return v8::internal::Registers::Name(reg);
+  return v8::internal::Register::from_code(reg).ToString();
 }
 
 
index 4ccb02099569aee044ec33830c78530edf620b48..87cbf0996c59ff640356a410bf01b53bd686d255 100644 (file)
@@ -444,14 +444,13 @@ LPlatformChunk* LChunkBuilder::Build() {
 
 
 LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
-  return new(zone()) LUnallocated(LUnallocated::FIXED_REGISTER,
-                                  Register::ToAllocationIndex(reg));
+  return new (zone()) LUnallocated(LUnallocated::FIXED_REGISTER, reg.code());
 }
 
 
 LUnallocated* LChunkBuilder::ToUnallocated(DoubleRegister reg) {
-  return new(zone()) LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER,
-                                  DoubleRegister::ToAllocationIndex(reg));
+  return new (zone())
+      LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER, reg.code());
 }
 
 
index b163061458ec1376cfd4623c957df2138a0df90c..80153ae7fc2e2ba507bf06b740174a41b0029e99 100644 (file)
@@ -72,7 +72,7 @@ void LCodeGen::SaveCallerDoubles() {
   BitVector* doubles = chunk()->allocated_double_registers();
   BitVector::Iterator save_iterator(doubles);
   while (!save_iterator.Done()) {
-    __ vstr(DwVfpRegister::FromAllocationIndex(save_iterator.Current()),
+    __ vstr(DoubleRegister::from_code(save_iterator.Current()),
             MemOperand(sp, count * kDoubleSize));
     save_iterator.Advance();
     count++;
@@ -88,8 +88,8 @@ void LCodeGen::RestoreCallerDoubles() {
   BitVector::Iterator save_iterator(doubles);
   int count = 0;
   while (!save_iterator.Done()) {
-    __ vldr(DwVfpRegister::FromAllocationIndex(save_iterator.Current()),
-             MemOperand(sp, count * kDoubleSize));
+    __ vldr(DoubleRegister::from_code(save_iterator.Current()),
+            MemOperand(sp, count * kDoubleSize));
     save_iterator.Advance();
     count++;
   }
@@ -405,13 +405,13 @@ bool LCodeGen::GenerateSafepointTable() {
 }
 
 
-Register LCodeGen::ToRegister(int index) const {
-  return Register::FromAllocationIndex(index);
+Register LCodeGen::ToRegister(int code) const {
+  return Register::from_code(code);
 }
 
 
-DwVfpRegister LCodeGen::ToDoubleRegister(int index) const {
-  return DwVfpRegister::FromAllocationIndex(index);
+DwVfpRegister LCodeGen::ToDoubleRegister(int code) const {
+  return DwVfpRegister::from_code(code);
 }
 
 
index da467ccc835eacbbcffbbd6a47e40fe63c5a65db..1e2df8046272b66da3a22b1d4743977e6fc8b741 100644 (file)
@@ -12,6 +12,7 @@
 #include "src/codegen.h"
 #include "src/cpu-profiler.h"
 #include "src/debug/debug.h"
+#include "src/register-configuration.h"
 #include "src/runtime/runtime.h"
 
 #include "src/arm/macro-assembler-arm.h"
@@ -760,7 +761,8 @@ MemOperand MacroAssembler::SafepointRegistersAndDoublesSlot(Register reg) {
   // Number of d-regs not known at snapshot time.
   DCHECK(!serializer_enabled());
   // General purpose registers are pushed last on the stack.
-  int doubles_size = DwVfpRegister::NumAllocatableRegisters() * kDoubleSize;
+  const RegisterConfiguration* config = RegisterConfiguration::ArchDefault();
+  int doubles_size = config->num_allocatable_double_registers() * kDoubleSize;
   int register_offset = SafepointRegisterStackIndex(reg.code()) * kPointerSize;
   return MemOperand(sp, doubles_size + register_offset);
 }
@@ -3571,8 +3573,10 @@ Register GetRegisterThatIsNotOneOf(Register reg1,
   if (reg5.is_valid()) regs |= reg5.bit();
   if (reg6.is_valid()) regs |= reg6.bit();
 
-  for (int i = 0; i < Register::NumAllocatableRegisters(); i++) {
-    Register candidate = Register::FromAllocationIndex(i);
+  const RegisterConfiguration* config = RegisterConfiguration::ArchDefault();
+  for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
+    int code = config->GetAllocatableGeneralCode(i);
+    Register candidate = Register::from_code(code);
     if (regs & candidate.bit()) continue;
     return candidate;
   }
index 8bb573f65eee82acef9610c3dd6c08fda373f867..5c596f2e3f4a70793120ac9eb747d6406b7037ee 100644 (file)
@@ -14,17 +14,17 @@ namespace v8 {
 namespace internal {
 
 // Give alias names to registers for calling conventions.
-const Register kReturnRegister0 = {kRegister_r0_Code};
-const Register kReturnRegister1 = {kRegister_r1_Code};
-const Register kJSFunctionRegister = {kRegister_r1_Code};
-const Register kContextRegister = {kRegister_r7_Code};
-const Register kInterpreterAccumulatorRegister = {kRegister_r0_Code};
-const Register kInterpreterRegisterFileRegister = {kRegister_r4_Code};
-const Register kInterpreterBytecodeOffsetRegister = {kRegister_r5_Code};
-const Register kInterpreterBytecodeArrayRegister = {kRegister_r6_Code};
-const Register kInterpreterDispatchTableRegister = {kRegister_r8_Code};
-const Register kRuntimeCallFunctionRegister = {kRegister_r1_Code};
-const Register kRuntimeCallArgCountRegister = {kRegister_r0_Code};
+const Register kReturnRegister0 = {Register::kCode_r0};
+const Register kReturnRegister1 = {Register::kCode_r1};
+const Register kJSFunctionRegister = {Register::kCode_r1};
+const Register kContextRegister = {Register::kCode_r7};
+const Register kInterpreterAccumulatorRegister = {Register::kCode_r0};
+const Register kInterpreterRegisterFileRegister = {Register::kCode_r4};
+const Register kInterpreterBytecodeOffsetRegister = {Register::kCode_r5};
+const Register kInterpreterBytecodeArrayRegister = {Register::kCode_r6};
+const Register kInterpreterDispatchTableRegister = {Register::kCode_r8};
+const Register kRuntimeCallFunctionRegister = {Register::kCode_r1};
+const Register kRuntimeCallArgCountRegister = {Register::kCode_r0};
 
 // ----------------------------------------------------------------------------
 // Static helper functions
@@ -36,9 +36,9 @@ inline MemOperand FieldMemOperand(Register object, int offset) {
 
 
 // Give alias names to registers
-const Register cp = { kRegister_r7_Code };  // JavaScript context pointer.
-const Register pp = { kRegister_r8_Code };  // Constant pool pointer.
-const Register kRootRegister = { kRegister_r10_Code };  // Roots array pointer.
+const Register cp = {Register::kCode_r7};  // JavaScript context pointer.
+const Register pp = {Register::kCode_r8};  // Constant pool pointer.
+const Register kRootRegister = {Register::kCode_r10};  // Roots array pointer.
 
 // Flags used for AllocateHeapNumber
 enum TaggingMode {
index 5da6204050b926f056d06b8dd576a3ff9514eec3..716e804e3a37986d72eab2ea1a98695d8c306817 100644 (file)
@@ -298,7 +298,8 @@ void ArmDebugger::Debug() {
           if (strcmp(arg1, "all") == 0) {
             for (int i = 0; i < kNumRegisters; i++) {
               value = GetRegisterValue(i);
-              PrintF("%3s: 0x%08x %10d", Registers::Name(i), value, value);
+              PrintF("%3s: 0x%08x %10d", Register::from_code(i).ToString(),
+                     value, value);
               if ((argc == 3 && strcmp(arg2, "fp") == 0) &&
                   i < 8 &&
                   (i % 2) == 0) {
index 37a2f5a29d006f1c753b2a0bb07a1183c1276893..0a1ecda9aa9b7c7883ef4eced453dd3035bd18f8 100644 (file)
@@ -35,6 +35,7 @@
 #include "src/arm64/frames-arm64.h"
 #include "src/base/bits.h"
 #include "src/base/cpu.h"
+#include "src/register-configuration.h"
 
 namespace v8 {
 namespace internal {
@@ -192,8 +193,10 @@ bool RelocInfo::IsInConstantPool() {
 Register GetAllocatableRegisterThatIsNotOneOf(Register reg1, Register reg2,
                                               Register reg3, Register reg4) {
   CPURegList regs(reg1, reg2, reg3, reg4);
-  for (int i = 0; i < Register::NumAllocatableRegisters(); i++) {
-    Register candidate = Register::FromAllocationIndex(i);
+  const RegisterConfiguration* config = RegisterConfiguration::ArchDefault();
+  for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
+    int code = config->GetAllocatableDoubleCode(i);
+    Register candidate = Register::from_code(code);
     if (regs.IncludesAliasOf(candidate)) continue;
     return candidate;
   }
index f20be8315e2f0bfb4c12ca1ab1175253feae85b4..95aabd0c8da480b354d0a742fb4772dd03bd8a60 100644 (file)
@@ -23,12 +23,36 @@ namespace internal {
 
 // -----------------------------------------------------------------------------
 // Registers.
-#define REGISTER_CODE_LIST(R)                                                  \
-R(0)  R(1)  R(2)  R(3)  R(4)  R(5)  R(6)  R(7)                                 \
-R(8)  R(9)  R(10) R(11) R(12) R(13) R(14) R(15)                                \
-R(16) R(17) R(18) R(19) R(20) R(21) R(22) R(23)                                \
-R(24) R(25) R(26) R(27) R(28) R(29) R(30) R(31)
-
+// clang-format off
+#define GENERAL_REGISTER_CODE_LIST(R)                     \
+  R(0)  R(1)  R(2)  R(3)  R(4)  R(5)  R(6)  R(7)          \
+  R(8)  R(9)  R(10) R(11) R(12) R(13) R(14) R(15)         \
+  R(16) R(17) R(18) R(19) R(20) R(21) R(22) R(23)         \
+  R(24) R(25) R(26) R(27) R(28) R(29) R(30) R(31)
+
+#define GENERAL_REGISTERS(R)                              \
+  R(x0)  R(x1)  R(x2)  R(x3)  R(x4)  R(x5)  R(x6)  R(x7)  \
+  R(x8)  R(x9)  R(x10) R(x11) R(x12) R(x13) R(x14) R(x15) \
+  R(x16) R(x17) R(x18) R(x19) R(x20) R(x21) R(x22) R(x23) \
+  R(x24) R(x25) R(x26) R(x27) R(x28) R(x29) R(x30) R(x31)
+
+#define ALLOCATABLE_GENERAL_REGISTERS(R)                  \
+  R(x0)  R(x1)  R(x2)  R(x3)  R(x4)  R(x5)  R(x6)  R(x7)  \
+  R(x8)  R(x9)  R(x10) R(x11) R(x12) R(x13) R(x14) R(x15) \
+  R(x18) R(x19) R(x20) R(x21) R(x22) R(x23) R(x24) R(x27)
+
+#define DOUBLE_REGISTERS(R)                               \
+  R(d0)  R(d1)  R(d2)  R(d3)  R(d4)  R(d5)  R(d6)  R(d7)  \
+  R(d8)  R(d9)  R(d10) R(d11) R(d12) R(d13) R(d14) R(d15) \
+  R(d16) R(d17) R(d18) R(d19) R(d20) R(d21) R(d22) R(d23) \
+  R(d24) R(d25) R(d26) R(d27) R(d28) R(d29) R(d30) R(d31)
+
+#define ALLOCATABLE_DOUBLE_REGISTERS(R)                   \
+  R(d0)  R(d1)  R(d2)  R(d3)  R(d4)  R(d5)  R(d6)  R(d7)  \
+  R(d8)  R(d9)  R(d10) R(d11) R(d12) R(d13) R(d14) R(d16) \
+  R(d17) R(d18) R(d19) R(d20) R(d21) R(d22) R(d23) R(d24) \
+  R(d25) R(d26) R(d27) R(d28)
+// clang-format on
 
 static const int kRegListSizeInBits = sizeof(RegList) * kBitsPerByte;
 
@@ -40,6 +64,14 @@ struct FPRegister;
 
 
 struct CPURegister {
+  enum Code {
+#define REGISTER_CODE(R) kCode_##R,
+    GENERAL_REGISTERS(REGISTER_CODE)
+#undef REGISTER_CODE
+        kAfterLast,
+    kCode_no_reg = -1
+  };
+
   enum RegisterType {
     // The kInvalid value is used to detect uninitialized static instances,
     // which are always zero-initialized before any constructors are called.
@@ -117,6 +149,8 @@ struct Register : public CPURegister {
     DCHECK(IsValidOrNone());
   }
 
+  const char* ToString();
+  bool IsAllocatable() const;
   bool IsValid() const {
     DCHECK(IsRegister() || IsNone());
     return IsValidRegister();
@@ -130,6 +164,7 @@ struct Register : public CPURegister {
   // A few of them may be unused for now.
 
   static const int kNumRegisters = kNumberOfRegisters;
+  STATIC_ASSERT(kNumRegisters == Code::kAfterLast);
   static int NumRegisters() { return kNumRegisters; }
 
   // We allow crankshaft to use the following registers:
@@ -146,70 +181,6 @@ struct Register : public CPURegister {
   //   - "low range"
   //   - "high range"
   //   - "context"
-  static const unsigned kAllocatableLowRangeBegin = 0;
-  static const unsigned kAllocatableLowRangeEnd = 15;
-  static const unsigned kAllocatableHighRangeBegin = 18;
-  static const unsigned kAllocatableHighRangeEnd = 24;
-  static const unsigned kAllocatableContext = 27;
-
-  // Gap between low and high ranges.
-  static const int kAllocatableRangeGapSize =
-      (kAllocatableHighRangeBegin - kAllocatableLowRangeEnd) - 1;
-
-  static const int kMaxNumAllocatableRegisters =
-      (kAllocatableLowRangeEnd - kAllocatableLowRangeBegin + 1) +
-      (kAllocatableHighRangeEnd - kAllocatableHighRangeBegin + 1) + 1;  // cp
-  static int NumAllocatableRegisters() { return kMaxNumAllocatableRegisters; }
-
-  // Return true if the register is one that crankshaft can allocate.
-  bool IsAllocatable() const {
-    return ((reg_code == kAllocatableContext) ||
-            (reg_code <= kAllocatableLowRangeEnd) ||
-            ((reg_code >= kAllocatableHighRangeBegin) &&
-             (reg_code <= kAllocatableHighRangeEnd)));
-  }
-
-  static Register FromAllocationIndex(unsigned index) {
-    DCHECK(index < static_cast<unsigned>(NumAllocatableRegisters()));
-    // cp is the last allocatable register.
-    if (index == (static_cast<unsigned>(NumAllocatableRegisters() - 1))) {
-      return from_code(kAllocatableContext);
-    }
-
-    // Handle low and high ranges.
-    return (index <= kAllocatableLowRangeEnd)
-        ? from_code(index)
-        : from_code(index + kAllocatableRangeGapSize);
-  }
-
-  static const char* AllocationIndexToString(int index) {
-    DCHECK((index >= 0) && (index < NumAllocatableRegisters()));
-    DCHECK((kAllocatableLowRangeBegin == 0) &&
-           (kAllocatableLowRangeEnd == 15) &&
-           (kAllocatableHighRangeBegin == 18) &&
-           (kAllocatableHighRangeEnd == 24) &&
-           (kAllocatableContext == 27));
-    const char* const names[] = {
-      "x0", "x1", "x2", "x3", "x4",
-      "x5", "x6", "x7", "x8", "x9",
-      "x10", "x11", "x12", "x13", "x14",
-      "x15", "x18", "x19", "x20", "x21",
-      "x22", "x23", "x24", "x27",
-    };
-    return names[index];
-  }
-
-  static int ToAllocationIndex(Register reg) {
-    DCHECK(reg.IsAllocatable());
-    unsigned code = reg.code();
-    if (code == kAllocatableContext) {
-      return NumAllocatableRegisters() - 1;
-    }
-
-    return (code <= kAllocatableLowRangeEnd)
-        ? code
-        : code - kAllocatableRangeGapSize;
-  }
 
   static Register from_code(int code) {
     // Always return an X register.
@@ -221,6 +192,14 @@ struct Register : public CPURegister {
 
 
 struct FPRegister : public CPURegister {
+  enum Code {
+#define REGISTER_CODE(R) kCode_##R,
+    DOUBLE_REGISTERS(REGISTER_CODE)
+#undef REGISTER_CODE
+        kAfterLast,
+    kCode_no_reg = -1
+  };
+
   static FPRegister Create(unsigned code, unsigned size) {
     return FPRegister(
         CPURegister::Create(code, size, CPURegister::kFPRegister));
@@ -246,6 +225,8 @@ struct FPRegister : public CPURegister {
     DCHECK(IsValidOrNone());
   }
 
+  const char* ToString();
+  bool IsAllocatable() const;
   bool IsValid() const {
     DCHECK(IsFPRegister() || IsNone());
     return IsValidFPRegister();
@@ -256,69 +237,12 @@ struct FPRegister : public CPURegister {
 
   // Start of V8 compatibility section ---------------------
   static const int kMaxNumRegisters = kNumberOfFPRegisters;
+  STATIC_ASSERT(kMaxNumRegisters == Code::kAfterLast);
 
   // Crankshaft can use all the FP registers except:
   //   - d15 which is used to keep the 0 double value
   //   - d30 which is used in crankshaft as a double scratch register
   //   - d31 which is used in the MacroAssembler as a double scratch register
-  static const unsigned kAllocatableLowRangeBegin = 0;
-  static const unsigned kAllocatableLowRangeEnd = 14;
-  static const unsigned kAllocatableHighRangeBegin = 16;
-  static const unsigned kAllocatableHighRangeEnd = 28;
-
-  static const RegList kAllocatableFPRegisters = 0x1fff7fff;
-
-  // Gap between low and high ranges.
-  static const int kAllocatableRangeGapSize =
-      (kAllocatableHighRangeBegin - kAllocatableLowRangeEnd) - 1;
-
-  static const int kMaxNumAllocatableRegisters =
-      (kAllocatableLowRangeEnd - kAllocatableLowRangeBegin + 1) +
-      (kAllocatableHighRangeEnd - kAllocatableHighRangeBegin + 1);
-  static int NumAllocatableRegisters() { return kMaxNumAllocatableRegisters; }
-
-  // TODO(turbofan): Proper float32 support.
-  static int NumAllocatableAliasedRegisters() {
-    return NumAllocatableRegisters();
-  }
-
-  // Return true if the register is one that crankshaft can allocate.
-  bool IsAllocatable() const {
-    return (Bit() & kAllocatableFPRegisters) != 0;
-  }
-
-  static FPRegister FromAllocationIndex(unsigned int index) {
-    DCHECK(index < static_cast<unsigned>(NumAllocatableRegisters()));
-
-    return (index <= kAllocatableLowRangeEnd)
-        ? from_code(index)
-        : from_code(index + kAllocatableRangeGapSize);
-  }
-
-  static const char* AllocationIndexToString(int index) {
-    DCHECK((index >= 0) && (index < NumAllocatableRegisters()));
-    DCHECK((kAllocatableLowRangeBegin == 0) &&
-           (kAllocatableLowRangeEnd == 14) &&
-           (kAllocatableHighRangeBegin == 16) &&
-           (kAllocatableHighRangeEnd == 28));
-    const char* const names[] = {
-      "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
-      "d8", "d9", "d10", "d11", "d12", "d13", "d14",
-      "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23",
-      "d24", "d25", "d26", "d27", "d28"
-    };
-    return names[index];
-  }
-
-  static int ToAllocationIndex(FPRegister reg) {
-    DCHECK(reg.IsAllocatable());
-    unsigned code = reg.code();
-
-    return (code <= kAllocatableLowRangeEnd)
-        ? code
-        : code - kAllocatableRangeGapSize;
-  }
-
   static FPRegister from_code(int code) {
     // Always return a D register.
     return FPRegister::Create(code, kDRegSizeInBits);
@@ -361,7 +285,7 @@ INITIALIZE_REGISTER(Register, no_reg, 0, 0, CPURegister::kNoRegister);
                       kWRegSizeInBits, CPURegister::kRegister);              \
   INITIALIZE_REGISTER(Register, x##N, N,                                     \
                       kXRegSizeInBits, CPURegister::kRegister);
-REGISTER_CODE_LIST(DEFINE_REGISTERS)
+GENERAL_REGISTER_CODE_LIST(DEFINE_REGISTERS)
 #undef DEFINE_REGISTERS
 
 INITIALIZE_REGISTER(Register, wcsp, kSPRegInternalCode, kWRegSizeInBits,
@@ -374,7 +298,7 @@ INITIALIZE_REGISTER(Register, csp, kSPRegInternalCode, kXRegSizeInBits,
                       kSRegSizeInBits, CPURegister::kFPRegister);              \
   INITIALIZE_REGISTER(FPRegister, d##N, N,                                     \
                       kDRegSizeInBits, CPURegister::kFPRegister);
-REGISTER_CODE_LIST(DEFINE_FPREGISTERS)
+GENERAL_REGISTER_CODE_LIST(DEFINE_FPREGISTERS)
 #undef DEFINE_FPREGISTERS
 
 #undef INITIALIZE_REGISTER
index 1529c647ff75c8ce6a81b5b94a82c9161b402da1..b419a6e85668e6fc503c96cf5c4491607ab9c7e0 100644 (file)
@@ -118,12 +118,6 @@ const unsigned kDoubleExponentBias = 1023;
 const unsigned kFloatMantissaBits = 23;
 const unsigned kFloatExponentBits = 8;
 
-#define REGISTER_CODE_LIST(R)                                                  \
-R(0)  R(1)  R(2)  R(3)  R(4)  R(5)  R(6)  R(7)                                 \
-R(8)  R(9)  R(10) R(11) R(12) R(13) R(14) R(15)                                \
-R(16) R(17) R(18) R(19) R(20) R(21) R(22) R(23)                                \
-R(24) R(25) R(26) R(27) R(28) R(29) R(30) R(31)
-
 #define INSTRUCTION_FIELDS_LIST(V_)                                            \
 /* Register fields */                                                          \
 V_(Rd, 4, 0, Bits)                        /* Destination register.     */      \
index 65fb93e53cfa2e87d555e3a937d6f5ffc8b99761..60409f6d267e0268e039ef62f9813979227c4081 100644 (file)
@@ -6,6 +6,7 @@
 #include "src/codegen.h"
 #include "src/deoptimizer.h"
 #include "src/full-codegen/full-codegen.h"
+#include "src/register-configuration.h"
 #include "src/safepoint-table.h"
 
 
@@ -75,7 +76,7 @@ void Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) {
   input_->SetRegister(jssp.code(), reinterpret_cast<intptr_t>(frame->sp()));
   input_->SetRegister(fp.code(), reinterpret_cast<intptr_t>(frame->fp()));
 
-  for (int i = 0; i < DoubleRegister::NumAllocatableRegisters(); i++) {
+  for (int i = 0; i < DoubleRegister::kMaxNumRegisters; i++) {
     input_->SetDoubleRegister(i, 0.0);
   }
 
@@ -122,8 +123,9 @@ void Deoptimizer::TableEntryGenerator::Generate() {
   // in the input frame.
 
   // Save all allocatable floating point registers.
-  CPURegList saved_fp_registers(CPURegister::kFPRegister, kDRegSizeInBits,
-                                FPRegister::kAllocatableFPRegisters);
+  CPURegList saved_fp_registers(
+      CPURegister::kFPRegister, kDRegSizeInBits,
+      RegisterConfiguration::ArchDefault()->allocatable_double_codes_mask());
   __ PushCPURegList(saved_fp_registers);
 
   // We save all the registers expcept jssp, sp and lr.
index e623718a1a323b59e9f672d335e08d22533f6ab3..5cc5b9d592eedc19a49ed4a2315a42f862d047e0 100644 (file)
@@ -375,14 +375,13 @@ const char* LArithmeticT::Mnemonic() const {
 
 
 LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
-  return new(zone()) LUnallocated(LUnallocated::FIXED_REGISTER,
-                                  Register::ToAllocationIndex(reg));
+  return new (zone()) LUnallocated(LUnallocated::FIXED_REGISTER, reg.code());
 }
 
 
 LUnallocated* LChunkBuilder::ToUnallocated(DoubleRegister reg) {
-  return new(zone()) LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER,
-                                  DoubleRegister::ToAllocationIndex(reg));
+  return new (zone())
+      LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER, reg.code());
 }
 
 
index 488e14f82c5b7ba974f099fddeb7344c9648583f..0067abfe240b671b6174fd227b0736cebdbc3fc3 100644 (file)
@@ -593,7 +593,7 @@ void LCodeGen::SaveCallerDoubles() {
   while (!iterator.Done()) {
     // TODO(all): Is this supposed to save just the callee-saved doubles? It
     // looks like it's saving all of them.
-    FPRegister value = FPRegister::FromAllocationIndex(iterator.Current());
+    FPRegister value = FPRegister::from_code(iterator.Current());
     __ Poke(value, count * kDoubleSize);
     iterator.Advance();
     count++;
@@ -611,7 +611,7 @@ void LCodeGen::RestoreCallerDoubles() {
   while (!iterator.Done()) {
     // TODO(all): Is this supposed to restore just the callee-saved doubles? It
     // looks like it's restoring all of them.
-    FPRegister value = FPRegister::FromAllocationIndex(iterator.Current());
+    FPRegister value = FPRegister::from_code(iterator.Current());
     __ Peek(value, count * kDoubleSize);
     iterator.Advance();
     count++;
@@ -1158,7 +1158,7 @@ void LCodeGen::EnsureSpaceForLazyDeopt(int space_needed) {
 Register LCodeGen::ToRegister(LOperand* op) const {
   // TODO(all): support zero register results, as ToRegister32.
   DCHECK((op != NULL) && op->IsRegister());
-  return Register::FromAllocationIndex(op->index());
+  return Register::from_code(op->index());
 }
 
 
@@ -1182,7 +1182,7 @@ Smi* LCodeGen::ToSmi(LConstantOperand* op) const {
 
 DoubleRegister LCodeGen::ToDoubleRegister(LOperand* op) const {
   DCHECK((op != NULL) && op->IsDoubleRegister());
-  return DoubleRegister::FromAllocationIndex(op->index());
+  return DoubleRegister::from_code(op->index());
 }
 
 
index 3c42194e0102fd4ee38a3b1cf46126557243f3d9..7aed57853bea070cd9a4d8a3be174ec93384ee9d 100644 (file)
@@ -10,6 +10,7 @@
 #include "src/codegen.h"
 #include "src/cpu-profiler.h"
 #include "src/debug/debug.h"
+#include "src/register-configuration.h"
 #include "src/runtime/runtime.h"
 
 #include "src/arm64/frames-arm64.h"
@@ -3977,14 +3978,16 @@ void MacroAssembler::PushSafepointRegisters() {
 
 void MacroAssembler::PushSafepointRegistersAndDoubles() {
   PushSafepointRegisters();
-  PushCPURegList(CPURegList(CPURegister::kFPRegister, kDRegSizeInBits,
-                            FPRegister::kAllocatableFPRegisters));
+  PushCPURegList(CPURegList(
+      CPURegister::kFPRegister, kDRegSizeInBits,
+      RegisterConfiguration::ArchDefault()->allocatable_double_codes_mask()));
 }
 
 
 void MacroAssembler::PopSafepointRegistersAndDoubles() {
-  PopCPURegList(CPURegList(CPURegister::kFPRegister, kDRegSizeInBits,
-                           FPRegister::kAllocatableFPRegisters));
+  PopCPURegList(CPURegList(
+      CPURegister::kFPRegister, kDRegSizeInBits,
+      RegisterConfiguration::ArchDefault()->allocatable_double_codes_mask()));
   PopSafepointRegisters();
 }
 
index e4d9a81ffdbe3d04305726efa911a83a8faaea37..ae7a91d3ed981880244463731da69cd82a5cad43 100644 (file)
 #include "src/globals.h"
 #include "src/utils.h"
 
-#define REGISTER_CODE_LIST(R)                                                  \
-R(0)  R(1)  R(2)  R(3)  R(4)  R(5)  R(6)  R(7)                                 \
-R(8)  R(9)  R(10) R(11) R(12) R(13) R(14) R(15)                                \
-R(16) R(17) R(18) R(19) R(20) R(21) R(22) R(23)                                \
-R(24) R(25) R(26) R(27) R(28) R(29) R(30) R(31)
-
 namespace v8 {
 namespace internal {
 
index da91fd5d6000aea74b6532b9233c58beebf852d3..cbc920b9c5f5c9eebb36cb0dcd6371c687128a87 100644 (file)
@@ -9,12 +9,6 @@
 
 #include "src/arm64/constants-arm64.h"
 
-#define REGISTER_CODE_LIST(R)                                                  \
-R(0)  R(1)  R(2)  R(3)  R(4)  R(5)  R(6)  R(7)                                 \
-R(8)  R(9)  R(10) R(11) R(12) R(13) R(14) R(15)                                \
-R(16) R(17) R(18) R(19) R(20) R(21) R(22) R(23)                                \
-R(24) R(25) R(26) R(27) R(28) R(29) R(30) R(31)
-
 namespace v8 {
 namespace internal {
 
index c81cdc2b78a39c4dc0f7a5cb5effdc661529ab48..b312915dfb7aa6e7bd6238d9dc3e5a564b2489c4 100644 (file)
@@ -53,6 +53,7 @@
 #include "src/regexp/jsregexp.h"
 #include "src/regexp/regexp-macro-assembler.h"
 #include "src/regexp/regexp-stack.h"
+#include "src/register-configuration.h"
 #include "src/runtime/runtime.h"
 #include "src/simulator.h"  // For flushing instruction cache.
 #include "src/snapshot/serialize.h"
 namespace v8 {
 namespace internal {
 
+// -----------------------------------------------------------------------------
+// Common register code.
+
+const char* Register::ToString() {
+  // This is the mapping of allocation indices to registers.
+  DCHECK(reg_code >= 0 && reg_code < kNumRegisters);
+  return RegisterConfiguration::ArchDefault()->GetGeneralRegisterName(reg_code);
+}
+
+
+bool Register::IsAllocatable() const {
+  return ((1 << reg_code) &
+          RegisterConfiguration::ArchDefault()
+              ->allocatable_general_codes_mask()) != 0;
+}
+
+
+const char* DoubleRegister::ToString() {
+  // This is the mapping of allocation indices to registers.
+  DCHECK(reg_code >= 0 && reg_code < kMaxNumRegisters);
+  return RegisterConfiguration::ArchDefault()->GetDoubleRegisterName(reg_code);
+}
+
+
+bool DoubleRegister::IsAllocatable() const {
+  return ((1 << reg_code) &
+          RegisterConfiguration::ArchDefault()
+              ->allocatable_double_codes_mask()) != 0;
+}
+
+
 // -----------------------------------------------------------------------------
 // Common double constants.
 
index 433b9b8456dc869ad6774e166b0bb9f8509c9c03..9810e5beb568d09853a7332269b0584f275d56c6 100644 (file)
@@ -1276,7 +1276,6 @@ class ConstantPoolBuilder BASE_EMBEDDED {
   PerTypeEntryInfo info_[ConstantPoolEntry::NUMBER_OF_TYPES];
 };
 
-
 } }  // namespace v8::internal
 
 #endif  // V8_ASSEMBLER_H_
index 76ddd2ed7d1d2cd26e8b3e218170f56d2494891c..59e8c86d88589e9e6c79b0bb39557596d515087c 100644 (file)
@@ -15,7 +15,7 @@ namespace compiler {
 
 namespace {
 LinkageLocation regloc(Register reg) {
-  return LinkageLocation::ForRegister(Register::ToAllocationIndex(reg));
+  return LinkageLocation::ForRegister(reg.code());
 }
 
 
index 83cbd22604a9fb921f6d58746f1d32128c4a0334..2e95bec0cc17188fbfc8d1997bbba90771d7fc3a 100644 (file)
@@ -96,12 +96,11 @@ class InstructionOperandConverter {
   }
 
   Register ToRegister(InstructionOperand* op) {
-    return Register::FromAllocationIndex(RegisterOperand::cast(op)->index());
+    return RegisterOperand::cast(op)->GetRegister();
   }
 
   DoubleRegister ToDoubleRegister(InstructionOperand* op) {
-    return DoubleRegister::FromAllocationIndex(
-        DoubleRegisterOperand::cast(op)->index());
+    return DoubleRegisterOperand::cast(op)->GetDoubleRegister();
   }
 
   Constant ToConstant(InstructionOperand* op) {
index 91602a02a3cde1de9f76bd20cd6ba8698c24012d..f702cce1c3c9b801849fa97e1e5d2958c47170a0 100644 (file)
@@ -227,8 +227,7 @@ void CodeGenerator::RecordSafepoint(ReferenceMap* references,
       index -= stackSlotToSpillSlotDelta;
       safepoint.DefinePointerSlot(index, zone());
     } else if (operand.IsRegister() && (kind & Safepoint::kWithRegisters)) {
-      Register reg =
-          Register::FromAllocationIndex(RegisterOperand::cast(operand).index());
+      Register reg = RegisterOperand::cast(operand).GetRegister();
       safepoint.DefinePointerRegister(reg, zone());
     }
   }
index 07ca04532bcaa3c94c95ea9d3b380d8167569f7c..47ca259e74dc7f96f9a9faa1ef2df92f960e5e00 100644 (file)
@@ -719,13 +719,13 @@ void GraphC1Visualizer::PrintLiveRange(LiveRange* range, const char* type,
     os_ << vreg << ":" << range->relative_id() << " " << type;
     if (range->HasRegisterAssigned()) {
       AllocatedOperand op = AllocatedOperand::cast(range->GetAssignedOperand());
-      int assigned_reg = op.index();
       if (op.IsDoubleRegister()) {
-        os_ << " \"" << DoubleRegister::AllocationIndexToString(assigned_reg)
-            << "\"";
+        DoubleRegister assigned_reg = op.GetDoubleRegister();
+        os_ << " \"" << assigned_reg.ToString() << "\"";
       } else {
         DCHECK(op.IsRegister());
-        os_ << " \"" << Register::AllocationIndexToString(assigned_reg) << "\"";
+        Register assigned_reg = op.GetRegister();
+        os_ << " \"" << assigned_reg.ToString() << "\"";
       }
     } else if (range->spilled()) {
       auto top = range->TopLevel();
index 88283d489877caeef91ed8e431c82e19a007d9fa..2ee099f9a8721df845a9640446632a67d0e050f7 100644 (file)
@@ -51,15 +51,13 @@ class OperandGenerator {
 
   InstructionOperand DefineAsFixed(Node* node, Register reg) {
     return Define(node, UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER,
-                                           Register::ToAllocationIndex(reg),
-                                           GetVReg(node)));
+                                           reg.code(), GetVReg(node)));
   }
 
   InstructionOperand DefineAsFixed(Node* node, DoubleRegister reg) {
     return Define(node,
                   UnallocatedOperand(UnallocatedOperand::FIXED_DOUBLE_REGISTER,
-                                     DoubleRegister::ToAllocationIndex(reg),
-                                     GetVReg(node)));
+                                     reg.code(), GetVReg(node)));
   }
 
   InstructionOperand DefineAsConstant(Node* node) {
@@ -107,15 +105,13 @@ class OperandGenerator {
 
   InstructionOperand UseFixed(Node* node, Register reg) {
     return Use(node, UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER,
-                                        Register::ToAllocationIndex(reg),
-                                        GetVReg(node)));
+                                        reg.code(), GetVReg(node)));
   }
 
   InstructionOperand UseFixed(Node* node, DoubleRegister reg) {
     return Use(node,
                UnallocatedOperand(UnallocatedOperand::FIXED_DOUBLE_REGISTER,
-                                  DoubleRegister::ToAllocationIndex(reg),
-                                  GetVReg(node)));
+                                  reg.code(), GetVReg(node)));
   }
 
   InstructionOperand UseImmediate(Node* node) {
@@ -142,8 +138,7 @@ class OperandGenerator {
   }
 
   InstructionOperand TempRegister(Register reg) {
-    return UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER,
-                              Register::ToAllocationIndex(reg),
+    return UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER, reg.code(),
                               InstructionOperand::kInvalidVirtualRegister);
   }
 
index 0fbb94979e41522d4df8d2472372559f4dab5160..a7ed0e5f236f7bae334f7810ee41efc80bcf624e 100644 (file)
@@ -74,11 +74,15 @@ std::ostream& operator<<(std::ostream& os,
         case UnallocatedOperand::NONE:
           return os;
         case UnallocatedOperand::FIXED_REGISTER:
-          return os << "(=" << conf->general_register_name(
-                                   unalloc->fixed_register_index()) << ")";
+          return os << "(="
+                    << conf->GetGeneralRegisterName(
+                           unalloc->fixed_register_index())
+                    << ")";
         case UnallocatedOperand::FIXED_DOUBLE_REGISTER:
-          return os << "(=" << conf->double_register_name(
-                                   unalloc->fixed_register_index()) << ")";
+          return os << "(="
+                    << conf->GetDoubleRegisterName(
+                           unalloc->fixed_register_index())
+                    << ")";
         case UnallocatedOperand::MUST_HAVE_REGISTER:
           return os << "(R)";
         case UnallocatedOperand::MUST_HAVE_SLOT:
@@ -111,14 +115,12 @@ std::ostream& operator<<(std::ostream& os,
           os << "[double_stack:" << DoubleStackSlotOperand::cast(op).index();
           break;
         case AllocatedOperand::REGISTER:
-          os << "["
-             << conf->general_register_name(RegisterOperand::cast(op).index())
+          os << "[" << RegisterOperand::cast(op).GetRegister().ToString()
              << "|R";
           break;
         case AllocatedOperand::DOUBLE_REGISTER:
-          os << "["
-             << conf->double_register_name(
-                    DoubleRegisterOperand::cast(op).index()) << "|R";
+          os << "[" << DoubleRegisterOperand::cast(op).GetRegister().ToString()
+             << "|R";
           break;
       }
       switch (allocated.machine_type()) {
index a0718f3c215a023a1c204b9d6b0ae746ee37c596..fab184adf8090681b2aec00dcc2cfb4964a6a8b4 100644 (file)
@@ -14,8 +14,9 @@
 #include "src/compiler/frame.h"
 #include "src/compiler/instruction-codes.h"
 #include "src/compiler/opcodes.h"
-#include "src/compiler/register-configuration.h"
 #include "src/compiler/source-position.h"
+#include "src/macro-assembler.h"
+#include "src/register-configuration.h"
 #include "src/zone-allocator.h"
 
 namespace v8 {
@@ -373,9 +374,23 @@ class AllocatedOperand : public InstructionOperand {
   }
 
   int index() const {
+    DCHECK(STACK_SLOT == allocated_kind() ||
+           DOUBLE_STACK_SLOT == allocated_kind());
     return static_cast<int64_t>(value_) >> IndexField::kShift;
   }
 
+  Register GetRegister() const {
+    DCHECK(REGISTER == allocated_kind() || DOUBLE_REGISTER == allocated_kind());
+    return Register::from_code(static_cast<int64_t>(value_) >>
+                               IndexField::kShift);
+  }
+
+  DoubleRegister GetDoubleRegister() const {
+    DCHECK(REGISTER == allocated_kind() || DOUBLE_REGISTER == allocated_kind());
+    return DoubleRegister::from_code(static_cast<int64_t>(value_) >>
+                                     IndexField::kShift);
+  }
+
   AllocatedKind allocated_kind() const {
     return AllocatedKindField::decode(value_);
   }
index 1def1d99b58f6abb8e53792d7c07a1d4409296c5..fd8aedc15da063fb5b8c940ee4eab62c520c2c15 100644 (file)
@@ -18,7 +18,7 @@ namespace compiler {
 
 namespace {
 LinkageLocation regloc(Register reg) {
-  return LinkageLocation::ForRegister(Register::ToAllocationIndex(reg));
+  return LinkageLocation::ForRegister(reg.code());
 }
 
 
index fd79a865e2403b423ab819043bdceb7443dfda8c..f767bd3cf3d6107878eeb82d643da2a11c072d33 100644 (file)
@@ -57,6 +57,7 @@
 #include "src/compiler/verifier.h"
 #include "src/compiler/zone-pool.h"
 #include "src/ostreams.h"
+#include "src/register-configuration.h"
 #include "src/type-info.h"
 #include "src/utils.h"
 
index 90c223f67ea6ef0529f934d264d1cd706a40cb9a..d437c7e585b1f4f2862820ba82894eb173d2548c 100644 (file)
@@ -11,6 +11,9 @@
 
 namespace v8 {
 namespace internal {
+
+class RegisterConfiguration;
+
 namespace compiler {
 
 class CallDescriptor;
@@ -18,7 +21,6 @@ class Graph;
 class InstructionSequence;
 class Linkage;
 class PipelineData;
-class RegisterConfiguration;
 class Schedule;
 
 class Pipeline {
index 0b775d29e1d83620eb1bc9504a5e8dd315f2dbbb..3b595b3b45d98d6222a8d44bb04e991db46f9695 100644 (file)
@@ -218,14 +218,16 @@ void RegisterAllocatorVerifier::CheckConstraint(
       return;
     case kFixedRegister:
       CHECK(op->IsRegister());
-      CHECK_EQ(RegisterOperand::cast(op)->index(), constraint->value_);
+      CHECK_EQ(RegisterOperand::cast(op)->GetDoubleRegister().code(),
+               constraint->value_);
       return;
     case kDoubleRegister:
       CHECK(op->IsDoubleRegister());
       return;
     case kFixedDoubleRegister:
       CHECK(op->IsDoubleRegister());
-      CHECK_EQ(DoubleRegisterOperand::cast(op)->index(), constraint->value_);
+      CHECK_EQ(DoubleRegisterOperand::cast(op)->GetDoubleRegister().code(),
+               constraint->value_);
       return;
     case kFixedSlot:
       CHECK(op->IsStackSlot());
index 840c13b1a779aacef537cdd85e94949feaed8a9f..64af331ade04cd2dfeaeb529939e1f206187c304 100644 (file)
@@ -27,11 +27,26 @@ void RemoveElement(ZoneVector<LiveRange*>* v, LiveRange* range) {
 
 
 int GetRegisterCount(const RegisterConfiguration* cfg, RegisterKind kind) {
-  return kind == DOUBLE_REGISTERS ? cfg->num_aliased_double_registers()
+  return kind == DOUBLE_REGISTERS ? cfg->num_double_registers()
                                   : cfg->num_general_registers();
 }
 
 
+int GetAllocatableRegisterCount(const RegisterConfiguration* cfg,
+                                RegisterKind kind) {
+  return kind == DOUBLE_REGISTERS
+             ? cfg->num_allocatable_aliased_double_registers()
+             : cfg->num_allocatable_general_registers();
+}
+
+
+const int* GetAllocatableRegisterCodes(const RegisterConfiguration* cfg,
+                                       RegisterKind kind) {
+  return kind == DOUBLE_REGISTERS ? cfg->allocatable_double_codes()
+                                  : cfg->allocatable_general_codes();
+}
+
+
 const InstructionBlock* GetContainingLoop(const InstructionSequence* sequence,
                                           const InstructionBlock* block) {
   auto index = block->loop_header();
@@ -52,11 +67,11 @@ Instruction* GetLastInstruction(InstructionSequence* code,
 }
 
 
-bool IsOutputRegisterOf(Instruction* instr, int index) {
+bool IsOutputRegisterOf(Instruction* instr, Register reg) {
   for (size_t i = 0; i < instr->OutputCount(); i++) {
     auto output = instr->OutputAt(i);
     if (output->IsRegister() &&
-        RegisterOperand::cast(output)->index() == index) {
+        RegisterOperand::cast(output)->GetRegister().is(reg)) {
       return true;
     }
   }
@@ -64,11 +79,11 @@ bool IsOutputRegisterOf(Instruction* instr, int index) {
 }
 
 
-bool IsOutputDoubleRegisterOf(Instruction* instr, int index) {
+bool IsOutputDoubleRegisterOf(Instruction* instr, DoubleRegister reg) {
   for (size_t i = 0; i < instr->OutputCount(); i++) {
     auto output = instr->OutputAt(i);
     if (output->IsDoubleRegister() &&
-        DoubleRegisterOperand::cast(output)->index() == index) {
+        DoubleRegisterOperand::cast(output)->GetDoubleRegister().is(reg)) {
       return true;
     }
   }
@@ -129,7 +144,7 @@ bool UsePosition::HasHint() const {
 }
 
 
-bool UsePosition::HintRegister(int* register_index) const {
+bool UsePosition::HintRegister(int* register_code) const {
   if (hint_ == nullptr) return false;
   switch (HintTypeField::decode(flags_)) {
     case UsePositionHintType::kNone:
@@ -139,20 +154,25 @@ bool UsePosition::HintRegister(int* register_index) const {
       auto use_pos = reinterpret_cast<UsePosition*>(hint_);
       int assigned_register = AssignedRegisterField::decode(use_pos->flags_);
       if (assigned_register == kUnassignedRegister) return false;
-      *register_index = assigned_register;
+      *register_code = assigned_register;
       return true;
     }
     case UsePositionHintType::kOperand: {
       auto operand = reinterpret_cast<InstructionOperand*>(hint_);
-      int assigned_register = AllocatedOperand::cast(operand)->index();
-      *register_index = assigned_register;
+      int assigned_register =
+          operand->IsRegister()
+              ? RegisterOperand::cast(operand)->GetRegister().code()
+              : DoubleRegisterOperand::cast(operand)
+                    ->GetDoubleRegister()
+                    .code();
+      *register_code = assigned_register;
       return true;
     }
     case UsePositionHintType::kPhi: {
       auto phi = reinterpret_cast<RegisterAllocationData::PhiMapValue*>(hint_);
       int assigned_register = phi->assigned_register();
       if (assigned_register == kUnassignedRegister) return false;
-      *register_index = assigned_register;
+      *register_code = assigned_register;
       return true;
     }
   }
@@ -1213,6 +1233,10 @@ RegisterAllocationData::RegisterAllocationData(
       debug_name_(debug_name),
       config_(config),
       phi_map_(allocation_zone()),
+      allocatable_codes_(this->config()->num_general_registers(), -1,
+                         allocation_zone()),
+      allocatable_double_codes_(this->config()->num_double_registers(), -1,
+                                allocation_zone()),
       live_in_sets_(code->InstructionBlockCount(), nullptr, allocation_zone()),
       live_out_sets_(code->InstructionBlockCount(), nullptr, allocation_zone()),
       live_ranges_(code->VirtualRegisterCount() * 2, nullptr,
@@ -1233,7 +1257,7 @@ RegisterAllocationData::RegisterAllocationData(
   assigned_registers_ = new (code_zone())
       BitVector(this->config()->num_general_registers(), code_zone());
   assigned_double_registers_ = new (code_zone())
-      BitVector(this->config()->num_aliased_double_registers(), code_zone());
+      BitVector(this->config()->num_double_registers(), code_zone());
   this->frame()->SetAllocatedRegisters(assigned_registers_);
   this->frame()->SetAllocatedDoubleRegisters(assigned_double_registers_);
 }
@@ -1772,7 +1796,7 @@ TopLevelLiveRange* LiveRangeBuilder::FixedLiveRangeFor(int index) {
 
 
 TopLevelLiveRange* LiveRangeBuilder::FixedDoubleLiveRangeFor(int index) {
-  DCHECK(index < config()->num_aliased_double_registers());
+  DCHECK(index < config()->num_double_registers());
   auto result = data()->fixed_double_live_ranges()[index];
   if (result == nullptr) {
     result = data()->NewLiveRange(FixedDoubleLiveRangeID(index), kRepFloat64);
@@ -1793,10 +1817,11 @@ TopLevelLiveRange* LiveRangeBuilder::LiveRangeFor(InstructionOperand* operand) {
     return data()->GetOrCreateLiveRangeFor(
         ConstantOperand::cast(operand)->virtual_register());
   } else if (operand->IsRegister()) {
-    return FixedLiveRangeFor(RegisterOperand::cast(operand)->index());
+    return FixedLiveRangeFor(
+        RegisterOperand::cast(operand)->GetRegister().code());
   } else if (operand->IsDoubleRegister()) {
     return FixedDoubleLiveRangeFor(
-        DoubleRegisterOperand::cast(operand)->index());
+        DoubleRegisterOperand::cast(operand)->GetDoubleRegister().code());
   } else {
     return nullptr;
   }
@@ -1886,9 +1911,10 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block,
     }
 
     if (instr->ClobbersRegisters()) {
-      for (int i = 0; i < config()->num_general_registers(); ++i) {
-        if (!IsOutputRegisterOf(instr, i)) {
-          auto range = FixedLiveRangeFor(i);
+      for (int i = 0; i < config()->num_allocatable_general_registers(); ++i) {
+        int code = config()->GetAllocatableGeneralCode(i);
+        if (!IsOutputRegisterOf(instr, Register::from_code(code))) {
+          auto range = FixedLiveRangeFor(code);
           range->AddUseInterval(curr_position, curr_position.End(),
                                 allocation_zone());
         }
@@ -1896,9 +1922,11 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block,
     }
 
     if (instr->ClobbersDoubleRegisters()) {
-      for (int i = 0; i < config()->num_aliased_double_registers(); ++i) {
-        if (!IsOutputDoubleRegisterOf(instr, i)) {
-          auto range = FixedDoubleLiveRangeFor(i);
+      for (int i = 0; i < config()->num_allocatable_aliased_double_registers();
+           ++i) {
+        int code = config()->GetAllocatableDoubleCode(i);
+        if (!IsOutputDoubleRegisterOf(instr, DoubleRegister::from_code(code))) {
+          auto range = FixedDoubleLiveRangeFor(code);
           range->AddUseInterval(curr_position, curr_position.End(),
                                 allocation_zone());
         }
@@ -2144,7 +2172,11 @@ RegisterAllocator::RegisterAllocator(RegisterAllocationData* data,
                                      RegisterKind kind)
     : data_(data),
       mode_(kind),
-      num_registers_(GetRegisterCount(data->config(), kind)) {}
+      num_registers_(GetRegisterCount(data->config(), kind)),
+      num_allocatable_registers_(
+          GetAllocatableRegisterCount(data->config(), kind)),
+      allocatable_register_codes_(
+          GetAllocatableRegisterCodes(data->config(), kind)) {}
 
 
 LiveRange* RegisterAllocator::SplitRangeAt(LiveRange* range,
@@ -2267,11 +2299,11 @@ const ZoneVector<TopLevelLiveRange*>& RegisterAllocator::GetFixedRegisters()
 }
 
 
-const char* RegisterAllocator::RegisterName(int allocation_index) const {
+const char* RegisterAllocator::RegisterName(int register_code) const {
   if (mode() == GENERAL_REGISTERS) {
-    return data()->config()->general_register_name(allocation_index);
+    return data()->config()->GetGeneralRegisterName(register_code);
   } else {
-    return data()->config()->double_register_name(allocation_index);
+    return data()->config()->GetDoubleRegisterName(register_code);
   }
 }
 
@@ -2510,6 +2542,9 @@ bool LinearScanAllocator::TryAllocateFreeReg(LiveRange* current) {
   for (auto cur_active : active_live_ranges()) {
     free_until_pos[cur_active->assigned_register()] =
         LifetimePosition::GapFromInstructionIndex(0);
+    TRACE("Register %s is free until pos %d (1)\n",
+          RegisterName(cur_active->assigned_register()),
+          LifetimePosition::GapFromInstructionIndex(0).value());
   }
 
   for (auto cur_inactive : inactive_live_ranges()) {
@@ -2518,6 +2553,8 @@ bool LinearScanAllocator::TryAllocateFreeReg(LiveRange* current) {
     if (!next_intersection.IsValid()) continue;
     int cur_reg = cur_inactive->assigned_register();
     free_until_pos[cur_reg] = Min(free_until_pos[cur_reg], next_intersection);
+    TRACE("Register %s is free until pos %d (2)\n", RegisterName(cur_reg),
+          Min(free_until_pos[cur_reg], next_intersection).value());
   }
 
   int hint_register;
@@ -2539,10 +2576,11 @@ bool LinearScanAllocator::TryAllocateFreeReg(LiveRange* current) {
   }
 
   // Find the register which stays free for the longest time.
-  int reg = 0;
-  for (int i = 1; i < num_registers(); ++i) {
-    if (free_until_pos[i] > free_until_pos[reg]) {
-      reg = i;
+  int reg = allocatable_register_code(0);
+  for (int i = 1; i < num_alloctable_registers(); ++i) {
+    int code = allocatable_register_code(i);
+    if (free_until_pos[code] > free_until_pos[reg]) {
+      reg = code;
     }
   }
 
@@ -2617,10 +2655,11 @@ void LinearScanAllocator::AllocateBlockedReg(LiveRange* current) {
     }
   }
 
-  int reg = 0;
-  for (int i = 1; i < num_registers(); ++i) {
-    if (use_pos[i] > use_pos[reg]) {
-      reg = i;
+  int reg = allocatable_register_code(0);
+  for (int i = 1; i < num_alloctable_registers(); ++i) {
+    int code = allocatable_register_code(i);
+    if (use_pos[code] > use_pos[reg]) {
+      reg = code;
     }
   }
 
index 117ddedbcd2a586337b9f68aee239af3333d4c4c..c0b4fd57d004d1e2d80acd61a0e53de76fb5ea1f 100644 (file)
@@ -7,6 +7,7 @@
 
 #include "src/compiler/instruction.h"
 #include "src/ostreams.h"
+#include "src/register-configuration.h"
 #include "src/zone-containers.h"
 
 namespace v8 {
@@ -241,15 +242,15 @@ class UsePosition final : public ZoneObject {
   void set_next(UsePosition* next) { next_ = next; }
 
   // For hinting only.
-  void set_assigned_register(int register_index) {
-    flags_ = AssignedRegisterField::update(flags_, register_index);
+  void set_assigned_register(int register_code) {
+    flags_ = AssignedRegisterField::update(flags_, register_code);
   }
 
   UsePositionHintType hint_type() const {
     return HintTypeField::decode(flags_);
   }
   bool HasHint() const;
-  bool HintRegister(int* register_index) const;
+  bool HintRegister(int* register_code) const;
   void ResolveHint(UsePosition* use_pos);
   bool IsResolved() const {
     return hint_type() != UsePositionHintType::kUnresolved;
@@ -666,9 +667,9 @@ class RegisterAllocationData final : public ZoneObject {
 
     // For hinting.
     int assigned_register() const { return assigned_register_; }
-    void set_assigned_register(int register_index) {
+    void set_assigned_register(int register_code) {
       DCHECK_EQ(assigned_register_, kUnassignedRegister);
-      assigned_register_ = register_index;
+      assigned_register_ = register_code;
     }
     void UnsetAssignedRegister() { assigned_register_ = kUnassignedRegister; }
 
@@ -769,6 +770,8 @@ class RegisterAllocationData final : public ZoneObject {
   const char* const debug_name_;
   const RegisterConfiguration* const config_;
   PhiMap phi_map_;
+  ZoneVector<int> allocatable_codes_;
+  ZoneVector<int> allocatable_double_codes_;
   ZoneVector<BitVector*> live_in_sets_;
   ZoneVector<BitVector*> live_out_sets_;
   ZoneVector<TopLevelLiveRange*> live_ranges_;
@@ -886,6 +889,10 @@ class RegisterAllocator : public ZoneObject {
   InstructionSequence* code() const { return data()->code(); }
   RegisterKind mode() const { return mode_; }
   int num_registers() const { return num_registers_; }
+  int num_alloctable_registers() const { return num_allocatable_registers_; }
+  int allocatable_register_code(int allocatable_index) const {
+    return allocatable_register_codes_[allocatable_index];
+  }
 
   Zone* allocation_zone() const { return data()->allocation_zone(); }
 
@@ -921,6 +928,8 @@ class RegisterAllocator : public ZoneObject {
   RegisterAllocationData* const data_;
   const RegisterKind mode_;
   const int num_registers_;
+  int num_allocatable_registers_;
+  const int* allocatable_register_codes_;
 
   DISALLOW_COPY_AND_ASSIGN(RegisterAllocator);
 };
diff --git a/src/compiler/register-configuration.cc b/src/compiler/register-configuration.cc
deleted file mode 100644 (file)
index ebe6cfe..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/compiler/register-configuration.h"
-#include "src/globals.h"
-#include "src/macro-assembler.h"
-
-namespace v8 {
-namespace internal {
-namespace compiler {
-
-namespace {
-
-STATIC_ASSERT(RegisterConfiguration::kMaxGeneralRegisters >=
-              Register::kNumRegisters);
-STATIC_ASSERT(RegisterConfiguration::kMaxDoubleRegisters >=
-              DoubleRegister::kMaxNumRegisters);
-
-class ArchDefaultRegisterConfiguration : public RegisterConfiguration {
- public:
-  ArchDefaultRegisterConfiguration()
-      : RegisterConfiguration(Register::kMaxNumAllocatableRegisters,
-#if V8_TARGET_ARCH_X87
-                              1,
-                              1,
-#else
-                              DoubleRegister::NumAllocatableRegisters(),
-                              DoubleRegister::NumAllocatableAliasedRegisters(),
-#endif
-                              general_register_name_table_,
-                              double_register_name_table_) {
-    DCHECK_EQ(Register::kMaxNumAllocatableRegisters,
-              Register::NumAllocatableRegisters());
-    for (int i = 0; i < Register::kMaxNumAllocatableRegisters; ++i) {
-      general_register_name_table_[i] = Register::AllocationIndexToString(i);
-    }
-    DCHECK_GE(DoubleRegister::kMaxNumAllocatableRegisters,
-              DoubleRegister::NumAllocatableRegisters());
-    for (int i = 0; i < DoubleRegister::NumAllocatableRegisters(); ++i) {
-      double_register_name_table_[i] =
-          DoubleRegister::AllocationIndexToString(i);
-    }
-  }
-
-  const char*
-      general_register_name_table_[Register::kMaxNumAllocatableRegisters];
-  const char*
-      double_register_name_table_[DoubleRegister::kMaxNumAllocatableRegisters];
-};
-
-
-static base::LazyInstance<ArchDefaultRegisterConfiguration>::type
-    kDefaultRegisterConfiguration = LAZY_INSTANCE_INITIALIZER;
-
-}  // namespace
-
-
-const RegisterConfiguration* RegisterConfiguration::ArchDefault() {
-  return &kDefaultRegisterConfiguration.Get();
-}
-
-RegisterConfiguration::RegisterConfiguration(
-    int num_general_registers, int num_double_registers,
-    int num_aliased_double_registers, const char* const* general_register_names,
-    const char* const* double_register_names)
-    : num_general_registers_(num_general_registers),
-      num_double_registers_(num_double_registers),
-      num_aliased_double_registers_(num_aliased_double_registers),
-      general_register_names_(general_register_names),
-      double_register_names_(double_register_names) {}
-
-
-}  // namespace compiler
-}  // namespace internal
-}  // namespace v8
diff --git a/src/compiler/register-configuration.h b/src/compiler/register-configuration.h
deleted file mode 100644 (file)
index f0d5873..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef V8_COMPILER_REGISTER_CONFIGURATION_H_
-#define V8_COMPILER_REGISTER_CONFIGURATION_H_
-
-#include "src/base/macros.h"
-
-namespace v8 {
-namespace internal {
-namespace compiler {
-
-// An architecture independent representation of the sets of registers available
-// for instruction creation.
-class RegisterConfiguration {
- public:
-  // Architecture independent maxes.
-  static const int kMaxGeneralRegisters = 32;
-  static const int kMaxDoubleRegisters = 32;
-
-  static const RegisterConfiguration* ArchDefault();
-
-  RegisterConfiguration(int num_general_registers, int num_double_registers,
-                        int num_aliased_double_registers,
-                        const char* const* general_register_name,
-                        const char* const* double_register_name);
-
-  int num_general_registers() const { return num_general_registers_; }
-  int num_double_registers() const { return num_double_registers_; }
-  int num_aliased_double_registers() const {
-    return num_aliased_double_registers_;
-  }
-
-  const char* general_register_name(int offset) const {
-    DCHECK(offset >= 0 && offset < kMaxGeneralRegisters);
-    return general_register_names_[offset];
-  }
-  const char* double_register_name(int offset) const {
-    DCHECK(offset >= 0 && offset < kMaxDoubleRegisters);
-    return double_register_names_[offset];
-  }
-
- private:
-  const int num_general_registers_;
-  const int num_double_registers_;
-  const int num_aliased_double_registers_;
-  const char* const* general_register_names_;
-  const char* const* double_register_names_;
-};
-
-}  // namespace compiler
-}  // namespace internal
-}  // namespace v8
-
-#endif  // V8_COMPILER_REGISTER_CONFIGURATION_H_
index b1f1576081153338d2359f47a10eb8c2c07e3c69..786a46640e758cd1a37399b11744db483c33a595 100644 (file)
@@ -2072,7 +2072,7 @@ void Translation::StoreBoolRegister(Register reg) {
 
 void Translation::StoreDoubleRegister(DoubleRegister reg) {
   buffer_->Add(DOUBLE_REGISTER, zone());
-  buffer_->Add(DoubleRegister::ToAllocationIndex(reg), zone());
+  buffer_->Add(reg.code(), zone());
 }
 
 
@@ -2925,7 +2925,7 @@ TranslatedValue TranslatedState::CreateNextTranslatedValue(
       double value = registers->GetDoubleRegister(input_reg);
       if (trace_file != nullptr) {
         PrintF(trace_file, "%e ; %s (bool)", value,
-               DoubleRegister::AllocationIndexToString(input_reg));
+               DoubleRegister::from_code(input_reg).ToString());
       }
       return TranslatedValue::NewDouble(this, value);
     }
index 76118dce23d6a40feaf1b97bc65c6d9570b2d5b7..99736aaf76163573464b107e077f991e349f941a 100644 (file)
@@ -11,6 +11,7 @@
 #include "src/deoptimizer.h"
 #include "src/frames-inl.h"
 #include "src/full-codegen/full-codegen.h"
+#include "src/register-configuration.h"
 #include "src/safepoint-table.h"
 #include "src/scopeinfo.h"
 #include "src/string-stream.h"
@@ -658,8 +659,9 @@ void StandardFrame::IterateCompiledFrame(ObjectVisitor* v) const {
   if (safepoint_entry.has_doubles()) {
     // Number of doubles not known at snapshot time.
     DCHECK(!isolate()->serializer_enabled());
-    parameters_base += DoubleRegister::NumAllocatableRegisters() *
-        kDoubleSize / kPointerSize;
+    parameters_base += RegisterConfiguration::ArchDefault()
+                           ->num_allocatable_double_registers() *
+                       kDoubleSize / kPointerSize;
   }
 
   // Visit the registers that contain pointers if any.
index 87f8ce9541495a9623642ccd0fd3e8e3eb5d8b72..ea4ca5e1c8504bc93f248828788e1bb90ceb32db 100644 (file)
@@ -13462,10 +13462,10 @@ void HTracer::TraceLiveRange(LiveRange* range, const char* type,
       int assigned_reg = op->index();
       if (op->IsDoubleRegister()) {
         trace_.Add(" \"%s\"",
-                   DoubleRegister::AllocationIndexToString(assigned_reg));
+                   DoubleRegister::from_code(assigned_reg).ToString());
       } else {
         DCHECK(op->IsRegister());
-        trace_.Add(" \"%s\"", Register::AllocationIndexToString(assigned_reg));
+        trace_.Add(" \"%s\"", Register::from_code(assigned_reg).ToString());
       }
     } else if (range->IsSpilled()) {
       LOperand* op = range->TopLevel()->GetSpillOperand();
index 57987bc7513c6337ae1dff885ddb9fba162f6430..38ad433fc850ff25d146faa6bb2e2e601b3de666 100644 (file)
 #include "src/assembler.h"
 #include "src/compiler.h"
 #include "src/isolate.h"
+#include "src/utils.h"
 
 namespace v8 {
 namespace internal {
 
+#define GENERAL_REGISTERS(V) \
+  V(eax)                     \
+  V(ecx)                     \
+  V(edx)                     \
+  V(ebx)                     \
+  V(esp)                     \
+  V(ebp)                     \
+  V(esi)                     \
+  V(edi)
+
+#define ALLOCATABLE_GENERAL_REGISTERS(V) \
+  V(eax)                                 \
+  V(ecx)                                 \
+  V(edx)                                 \
+  V(ebx)                                 \
+  V(esi)                                 \
+  V(edi)
+
+#define DOUBLE_REGISTERS(V) \
+  V(xmm0)                   \
+  V(xmm1)                   \
+  V(xmm2)                   \
+  V(xmm3)                   \
+  V(xmm4)                   \
+  V(xmm5)                   \
+  V(xmm6)                   \
+  V(xmm7)
+
+#define ALLOCATABLE_DOUBLE_REGISTERS(V) \
+  V(xmm1)                               \
+  V(xmm2)                               \
+  V(xmm3)                               \
+  V(xmm4)                               \
+  V(xmm5)                               \
+  V(xmm6)                               \
+  V(xmm7)
+
 // CPU Registers.
 //
 // 1) We would prefer to use an enum, but enum values are assignment-
@@ -68,151 +106,86 @@ namespace internal {
 // and best performance in optimized code.
 //
 struct Register {
-  static const int kMaxNumAllocatableRegisters = 6;
-  static int NumAllocatableRegisters() {
-    return kMaxNumAllocatableRegisters;
-  }
-  static const int kNumRegisters = 8;
-
-  static inline const char* AllocationIndexToString(int index);
+  enum Code {
+#define REGISTER_CODE(R) kCode_##R,
+    GENERAL_REGISTERS(REGISTER_CODE)
+#undef REGISTER_CODE
+        kAfterLast,
+    kCode_no_reg = -1
+  };
 
-  static inline int ToAllocationIndex(Register reg);
-
-  static inline Register FromAllocationIndex(int index);
+  static const int kNumRegisters = Code::kAfterLast;
 
   static Register from_code(int code) {
     DCHECK(code >= 0);
     DCHECK(code < kNumRegisters);
-    Register r = { code };
+    Register r = {code};
     return r;
   }
-  bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
-  bool is(Register reg) const { return code_ == reg.code_; }
-  // eax, ebx, ecx and edx are byte registers, the rest are not.
-  bool is_byte_register() const { return code_ <= 3; }
+  const char* ToString();
+  bool IsAllocatable() const;
+  bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; }
+  bool is(Register reg) const { return reg_code == reg.reg_code; }
   int code() const {
     DCHECK(is_valid());
-    return code_;
+    return reg_code;
   }
   int bit() const {
     DCHECK(is_valid());
-    return 1 << code_;
+    return 1 << reg_code;
   }
 
+  bool is_byte_register() const { return reg_code <= 3; }
+
   // Unfortunately we can't make this private in a struct.
-  int code_;
+  int reg_code;
 };
 
-const int kRegister_eax_Code = 0;
-const int kRegister_ecx_Code = 1;
-const int kRegister_edx_Code = 2;
-const int kRegister_ebx_Code = 3;
-const int kRegister_esp_Code = 4;
-const int kRegister_ebp_Code = 5;
-const int kRegister_esi_Code = 6;
-const int kRegister_edi_Code = 7;
-const int kRegister_no_reg_Code = -1;
-
-const Register eax = { kRegister_eax_Code };
-const Register ecx = { kRegister_ecx_Code };
-const Register edx = { kRegister_edx_Code };
-const Register ebx = { kRegister_ebx_Code };
-const Register esp = { kRegister_esp_Code };
-const Register ebp = { kRegister_ebp_Code };
-const Register esi = { kRegister_esi_Code };
-const Register edi = { kRegister_edi_Code };
-const Register no_reg = { kRegister_no_reg_Code };
-
-
-inline const char* Register::AllocationIndexToString(int index) {
-  DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
-  // This is the mapping of allocation indices to registers.
-  const char* const kNames[] = { "eax", "ecx", "edx", "ebx", "esi", "edi" };
-  return kNames[index];
-}
-
-
-inline int Register::ToAllocationIndex(Register reg) {
-  DCHECK(reg.is_valid() && !reg.is(esp) && !reg.is(ebp));
-  return (reg.code() >= 6) ? reg.code() - 2 : reg.code();
-}
-
-
-inline Register Register::FromAllocationIndex(int index)  {
-  DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
-  return (index >= 4) ? from_code(index + 2) : from_code(index);
-}
-
 
-struct XMMRegister {
-  static const int kMaxNumAllocatableRegisters = 7;
-  static const int kMaxNumRegisters = 8;
-  static int NumAllocatableRegisters() {
-    return kMaxNumAllocatableRegisters;
-  }
+#define DECLARE_REGISTER(R) const Register R = {Register::kCode_##R};
+GENERAL_REGISTERS(DECLARE_REGISTER)
+#undef DECLARE_REGISTER
+const Register no_reg = {Register::kCode_no_reg};
 
-  // TODO(turbofan): Proper support for float32.
-  static int NumAllocatableAliasedRegisters() {
-    return NumAllocatableRegisters();
-  }
 
-  static int ToAllocationIndex(XMMRegister reg) {
-    DCHECK(reg.code() != 0);
-    return reg.code() - 1;
-  }
+struct DoubleRegister {
+  enum Code {
+#define REGISTER_CODE(R) kCode_##R,
+    DOUBLE_REGISTERS(REGISTER_CODE)
+#undef REGISTER_CODE
+        kAfterLast,
+    kCode_no_reg = -1
+  };
 
-  static XMMRegister FromAllocationIndex(int index) {
-    DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
-    return from_code(index + 1);
-  }
+  static const int kMaxNumRegisters = Code::kAfterLast;
 
-  static XMMRegister from_code(int code) {
-    XMMRegister result = { code };
+  static DoubleRegister from_code(int code) {
+    DoubleRegister result = {code};
     return result;
   }
 
-  bool is_valid() const {
-    return 0 <= code_ && code_ < kMaxNumRegisters;
-  }
+  bool IsAllocatable() const;
+  bool is_valid() const { return 0 <= reg_code && reg_code < kMaxNumRegisters; }
 
   int code() const {
     DCHECK(is_valid());
-    return code_;
+    return reg_code;
   }
 
-  bool is(XMMRegister reg) const { return code_ == reg.code_; }
+  bool is(DoubleRegister reg) const { return reg_code == reg.reg_code; }
 
-  static const char* AllocationIndexToString(int index) {
-    DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
-    const char* const names[] = {
-      "xmm1",
-      "xmm2",
-      "xmm3",
-      "xmm4",
-      "xmm5",
-      "xmm6",
-      "xmm7"
-    };
-    return names[index];
-  }
+  const char* ToString();
 
-  int code_;
+  int reg_code;
 };
 
+#define DECLARE_REGISTER(R) \
+  const DoubleRegister R = {DoubleRegister::kCode_##R};
+DOUBLE_REGISTERS(DECLARE_REGISTER)
+#undef DECLARE_REGISTER
+const DoubleRegister no_double_reg = {DoubleRegister::kCode_no_reg};
 
-typedef XMMRegister DoubleRegister;
-
-
-const XMMRegister xmm0 = { 0 };
-const XMMRegister xmm1 = { 1 };
-const XMMRegister xmm2 = { 2 };
-const XMMRegister xmm3 = { 3 };
-const XMMRegister xmm4 = { 4 };
-const XMMRegister xmm5 = { 5 };
-const XMMRegister xmm6 = { 6 };
-const XMMRegister xmm7 = { 7 };
-const XMMRegister no_xmm_reg = { -1 };
-
+typedef DoubleRegister XMMRegister;
 
 enum Condition {
   // any value < 0 is considered no_condition
index c09b27b773e2a538fa16498d380bbe1e78f5a75f..dabd9c08f3850a66013bd169f605539ca056db20 100644 (file)
@@ -320,13 +320,15 @@ class RecordWriteStub: public PlatformCodeStub {
     Register GetRegThatIsNotEcxOr(Register r1,
                                   Register r2,
                                   Register r3) {
-      for (int i = 0; i < Register::NumAllocatableRegisters(); i++) {
-        Register candidate = Register::FromAllocationIndex(i);
-        if (candidate.is(ecx)) continue;
-        if (candidate.is(r1)) continue;
-        if (candidate.is(r2)) continue;
-        if (candidate.is(r3)) continue;
-        return candidate;
+      for (int i = 0; i < Register::kNumRegisters; i++) {
+        Register candidate = Register::from_code(i);
+        if (candidate.IsAllocatable()) {
+          if (candidate.is(ecx)) continue;
+          if (candidate.is(r1)) continue;
+          if (candidate.is(r2)) continue;
+          if (candidate.is(r3)) continue;
+          return candidate;
+        }
       }
       UNREACHABLE();
       return no_reg;
index d804f630ea8e5fa6f5744d1e6b78fe334b9a3efb..756922a1cedf2fb1a8475ab4aca0e3746db7dc50 100644 (file)
@@ -8,6 +8,7 @@
 #include "src/deoptimizer.h"
 #include "src/full-codegen/full-codegen.h"
 #include "src/ia32/frames-ia32.h"
+#include "src/register-configuration.h"
 #include "src/safepoint-table.h"
 
 namespace v8 {
@@ -181,7 +182,7 @@ void Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) {
   }
   input_->SetRegister(esp.code(), reinterpret_cast<intptr_t>(frame->sp()));
   input_->SetRegister(ebp.code(), reinterpret_cast<intptr_t>(frame->fp()));
-  for (int i = 0; i < XMMRegister::kMaxNumAllocatableRegisters; i++) {
+  for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) {
     input_->SetDoubleRegister(i, 0.0);
   }
 
@@ -203,7 +204,7 @@ void Deoptimizer::SetPlatformCompiledStubRegisters(
 
 
 void Deoptimizer::CopyDoubleRegisters(FrameDescription* output_frame) {
-  for (int i = 0; i < XMMRegister::kMaxNumAllocatableRegisters; ++i) {
+  for (int i = 0; i < XMMRegister::kMaxNumRegisters; ++i) {
     double double_value = input_->GetDoubleRegister(i);
     output_frame->SetDoubleRegister(i, double_value);
   }
@@ -233,12 +234,13 @@ void Deoptimizer::TableEntryGenerator::Generate() {
   // Save all general purpose registers before messing with them.
   const int kNumberOfRegisters = Register::kNumRegisters;
 
-  const int kDoubleRegsSize = kDoubleSize *
-                              XMMRegister::kMaxNumAllocatableRegisters;
+  const int kDoubleRegsSize = kDoubleSize * XMMRegister::kMaxNumRegisters;
   __ sub(esp, Immediate(kDoubleRegsSize));
-  for (int i = 0; i < XMMRegister::kMaxNumAllocatableRegisters; ++i) {
-    XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i);
-    int offset = i * kDoubleSize;
+  const RegisterConfiguration* config = RegisterConfiguration::ArchDefault();
+  for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
+    int code = config->GetAllocatableDoubleCode(i);
+    XMMRegister xmm_reg = XMMRegister::from_code(code);
+    int offset = code * kDoubleSize;
     __ movsd(Operand(esp, offset), xmm_reg);
   }
 
@@ -288,9 +290,10 @@ void Deoptimizer::TableEntryGenerator::Generate() {
 
   int double_regs_offset = FrameDescription::double_registers_offset();
   // Fill in the double input registers.
-  for (int i = 0; i < XMMRegister::kMaxNumAllocatableRegisters; ++i) {
-    int dst_offset = i * kDoubleSize + double_regs_offset;
-    int src_offset = i * kDoubleSize;
+  for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
+    int code = config->GetAllocatableDoubleCode(i);
+    int dst_offset = code * kDoubleSize + double_regs_offset;
+    int src_offset = code * kDoubleSize;
     __ movsd(xmm0, Operand(esp, src_offset));
     __ movsd(Operand(ebx, dst_offset), xmm0);
   }
@@ -371,9 +374,10 @@ void Deoptimizer::TableEntryGenerator::Generate() {
   __ j(below, &outer_push_loop);
 
   // In case of a failed STUB, we have to restore the XMM registers.
-  for (int i = 0; i < XMMRegister::kMaxNumAllocatableRegisters; ++i) {
-    XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i);
-    int src_offset = i * kDoubleSize + double_regs_offset;
+  for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
+    int code = config->GetAllocatableDoubleCode(i);
+    XMMRegister xmm_reg = XMMRegister::from_code(code);
+    int src_offset = code * kDoubleSize + double_regs_offset;
     __ movsd(xmm_reg, Operand(ebx, src_offset));
   }
 
index 99c0938b6a4b5110d0b28a7f70c61c2c9ac9c732..55438ad888620a2275c897b1e6b719f27739f34e 100644 (file)
@@ -101,7 +101,7 @@ void LCodeGen::SaveCallerDoubles() {
   BitVector::Iterator save_iterator(doubles);
   while (!save_iterator.Done()) {
     __ movsd(MemOperand(esp, count * kDoubleSize),
-              XMMRegister::FromAllocationIndex(save_iterator.Current()));
+             XMMRegister::from_code(save_iterator.Current()));
     save_iterator.Advance();
     count++;
   }
@@ -116,8 +116,8 @@ void LCodeGen::RestoreCallerDoubles() {
   BitVector::Iterator save_iterator(doubles);
   int count = 0;
   while (!save_iterator.Done()) {
-    __ movsd(XMMRegister::FromAllocationIndex(save_iterator.Current()),
-              MemOperand(esp, count * kDoubleSize));
+    __ movsd(XMMRegister::from_code(save_iterator.Current()),
+             MemOperand(esp, count * kDoubleSize));
     save_iterator.Advance();
     count++;
   }
@@ -515,13 +515,13 @@ bool LCodeGen::GenerateSafepointTable() {
 }
 
 
-Register LCodeGen::ToRegister(int index) const {
-  return Register::FromAllocationIndex(index);
+Register LCodeGen::ToRegister(int code) const {
+  return Register::from_code(code);
 }
 
 
-XMMRegister LCodeGen::ToDoubleRegister(int index) const {
-  return XMMRegister::FromAllocationIndex(index);
+XMMRegister LCodeGen::ToDoubleRegister(int code) const {
+  return XMMRegister::from_code(code);
 }
 
 
index 0926a0f21a1d4b0a873998232e3a8d501a880d1a..655f4a2efb71e633fe62b2d06b9d91c7817a5145 100644 (file)
@@ -6,6 +6,7 @@
 
 #include "src/ia32/lithium-codegen-ia32.h"
 #include "src/ia32/lithium-gap-resolver-ia32.h"
+#include "src/register-configuration.h"
 
 namespace v8 {
 namespace internal {
@@ -165,10 +166,13 @@ int LGapResolver::CountSourceUses(LOperand* operand) {
 
 
 Register LGapResolver::GetFreeRegisterNot(Register reg) {
-  int skip_index = reg.is(no_reg) ? -1 : Register::ToAllocationIndex(reg);
-  for (int i = 0; i < Register::NumAllocatableRegisters(); ++i) {
-    if (source_uses_[i] == 0 && destination_uses_[i] > 0 && i != skip_index) {
-      return Register::FromAllocationIndex(i);
+  int skip_index = reg.is(no_reg) ? -1 : reg.code();
+  const RegisterConfiguration* config = RegisterConfiguration::ArchDefault();
+  for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
+    int code = config->GetAllocatableGeneralCode(i);
+    if (source_uses_[code] == 0 && destination_uses_[code] > 0 &&
+        code != skip_index) {
+      return Register::from_code(code);
     }
   }
   return no_reg;
@@ -178,10 +182,11 @@ Register LGapResolver::GetFreeRegisterNot(Register reg) {
 bool LGapResolver::HasBeenReset() {
   if (!moves_.is_empty()) return false;
   if (spilled_register_ >= 0) return false;
-
-  for (int i = 0; i < Register::NumAllocatableRegisters(); ++i) {
-    if (source_uses_[i] != 0) return false;
-    if (destination_uses_[i] != 0) return false;
+  const RegisterConfiguration* config = RegisterConfiguration::ArchDefault();
+  for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
+    int code = config->GetAllocatableGeneralCode(i);
+    if (source_uses_[code] != 0) return false;
+    if (destination_uses_[code] != 0) return false;
   }
   return true;
 }
@@ -204,7 +209,7 @@ void LGapResolver::Verify() {
 
 void LGapResolver::Finish() {
   if (spilled_register_ >= 0) {
-    __ pop(Register::FromAllocationIndex(spilled_register_));
+    __ pop(Register::from_code(spilled_register_));
     spilled_register_ = -1;
   }
   moves_.Rewind(0);
@@ -213,7 +218,7 @@ void LGapResolver::Finish() {
 
 void LGapResolver::EnsureRestored(LOperand* operand) {
   if (operand->IsRegister() && operand->index() == spilled_register_) {
-    __ pop(Register::FromAllocationIndex(spilled_register_));
+    __ pop(Register::from_code(spilled_register_));
     spilled_register_ = -1;
   }
 }
@@ -222,7 +227,7 @@ void LGapResolver::EnsureRestored(LOperand* operand) {
 Register LGapResolver::EnsureTempRegister() {
   // 1. We may have already spilled to create a temp register.
   if (spilled_register_ >= 0) {
-    return Register::FromAllocationIndex(spilled_register_);
+    return Register::from_code(spilled_register_);
   }
 
   // 2. We may have a free register that we can use without spilling.
@@ -231,19 +236,21 @@ Register LGapResolver::EnsureTempRegister() {
 
   // 3. Prefer to spill a register that is not used in any remaining move
   // because it will not need to be restored until the end.
-  for (int i = 0; i < Register::NumAllocatableRegisters(); ++i) {
-    if (source_uses_[i] == 0 && destination_uses_[i] == 0) {
-      Register scratch = Register::FromAllocationIndex(i);
+  const RegisterConfiguration* config = RegisterConfiguration::ArchDefault();
+  for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
+    int code = config->GetAllocatableGeneralCode(i);
+    if (source_uses_[code] == 0 && destination_uses_[code] == 0) {
+      Register scratch = Register::from_code(code);
       __ push(scratch);
-      spilled_register_ = i;
+      spilled_register_ = code;
       return scratch;
     }
   }
 
   // 4. Use an arbitrary register.  Register 0 is as arbitrary as any other.
-  Register scratch = Register::FromAllocationIndex(0);
+  spilled_register_ = config->GetAllocatableGeneralCode(0);
+  Register scratch = Register::from_code(spilled_register_);
   __ push(scratch);
-  spilled_register_ = 0;
   return scratch;
 }
 
index d36e78b5f668c2d461fdeb4f73fcae7298bbea50..f9921450c044442dddecabb6d1c24f49b9d6ebe0 100644 (file)
@@ -72,8 +72,8 @@ class LGapResolver final BASE_EMBEDDED {
   ZoneList<LMoveOperands> moves_;
 
   // Source and destination use counts for the general purpose registers.
-  int source_uses_[Register::kMaxNumAllocatableRegisters];
-  int destination_uses_[Register::kMaxNumAllocatableRegisters];
+  int source_uses_[Register::kNumRegisters];
+  int destination_uses_[DoubleRegister::kMaxNumRegisters];
 
   // If we had to spill on demand, the currently spilled register's
   // allocation index.
index 884067b776e417e086b948c93d52d9d362d78083..262e16bcbd8c5230ce5f8bcc7d5c3af3df379fde 100644 (file)
@@ -482,14 +482,13 @@ LPlatformChunk* LChunkBuilder::Build() {
 
 
 LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
-  return new(zone()) LUnallocated(LUnallocated::FIXED_REGISTER,
-                                  Register::ToAllocationIndex(reg));
+  return new (zone()) LUnallocated(LUnallocated::FIXED_REGISTER, reg.code());
 }
 
 
 LUnallocated* LChunkBuilder::ToUnallocated(XMMRegister reg) {
-  return new(zone()) LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER,
-                                  XMMRegister::ToAllocationIndex(reg));
+  return new (zone())
+      LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER, reg.code());
 }
 
 
index 2a2338dc07f20b3cca39bfdab6531baa3d64db7d..d2f04317f2acf6f4eb944827bd0595da2a58cf8b 100644 (file)
@@ -14,17 +14,17 @@ namespace v8 {
 namespace internal {
 
 // Give alias names to registers for calling conventions.
-const Register kReturnRegister0 = {kRegister_eax_Code};
-const Register kReturnRegister1 = {kRegister_edx_Code};
-const Register kJSFunctionRegister = {kRegister_edi_Code};
-const Register kContextRegister = {kRegister_esi_Code};
-const Register kInterpreterAccumulatorRegister = {kRegister_eax_Code};
-const Register kInterpreterRegisterFileRegister = {kRegister_edx_Code};
-const Register kInterpreterBytecodeOffsetRegister = {kRegister_ecx_Code};
-const Register kInterpreterBytecodeArrayRegister = {kRegister_edi_Code};
-const Register kInterpreterDispatchTableRegister = {kRegister_ebx_Code};
-const Register kRuntimeCallFunctionRegister = {kRegister_ebx_Code};
-const Register kRuntimeCallArgCountRegister = {kRegister_eax_Code};
+const Register kReturnRegister0 = {Register::kCode_eax};
+const Register kReturnRegister1 = {Register::kCode_edx};
+const Register kJSFunctionRegister = {Register::kCode_edi};
+const Register kContextRegister = {Register::kCode_esi};
+const Register kInterpreterAccumulatorRegister = {Register::kCode_eax};
+const Register kInterpreterRegisterFileRegister = {Register::kCode_edx};
+const Register kInterpreterBytecodeOffsetRegister = {Register::kCode_ecx};
+const Register kInterpreterBytecodeArrayRegister = {Register::kCode_edi};
+const Register kInterpreterDispatchTableRegister = {Register::kCode_ebx};
+const Register kRuntimeCallFunctionRegister = {Register::kCode_ebx};
+const Register kRuntimeCallArgCountRegister = {Register::kCode_eax};
 
 // Spill slots used by interpreter dispatch calling convention.
 const int kInterpreterContextSpillSlot = -1;
index 36a12e75b3bcde312b01fc0564212fb4fc60f839..7e34daab411dba2f93ff19e838c511fca1b83236 100644 (file)
@@ -7,6 +7,7 @@
 #include "src/hydrogen.h"
 #include "src/lithium-inl.h"
 #include "src/lithium-allocator-inl.h"
+#include "src/register-configuration.h"
 #include "src/string-stream.h"
 
 namespace v8 {
@@ -585,7 +586,7 @@ void LAllocator::AddInitialIntervals(HBasicBlock* block,
 
 
 int LAllocator::FixedDoubleLiveRangeID(int index) {
-  return -index - 1 - Register::kMaxNumAllocatableRegisters;
+  return -index - 1 - Register::kNumRegisters;
 }
 
 
@@ -617,7 +618,7 @@ LOperand* LAllocator::AllocateFixed(LUnallocated* operand,
 
 
 LiveRange* LAllocator::FixedLiveRangeFor(int index) {
-  DCHECK(index < Register::kMaxNumAllocatableRegisters);
+  DCHECK(index < Register::kNumRegisters);
   LiveRange* result = fixed_live_ranges_[index];
   if (result == NULL) {
     result = new(zone()) LiveRange(FixedLiveRangeID(index), chunk()->zone());
@@ -631,7 +632,7 @@ LiveRange* LAllocator::FixedLiveRangeFor(int index) {
 
 
 LiveRange* LAllocator::FixedDoubleLiveRangeFor(int index) {
-  DCHECK(index < DoubleRegister::NumAllocatableRegisters());
+  DCHECK(index < DoubleRegister::kMaxNumRegisters);
   LiveRange* result = fixed_double_live_ranges_[index];
   if (result == NULL) {
     result = new(zone()) LiveRange(FixedDoubleLiveRangeID(index),
@@ -939,25 +940,27 @@ void LAllocator::ProcessInstructions(HBasicBlock* block, BitVector* live) {
         }
 
         if (instr->ClobbersRegisters()) {
-          for (int i = 0; i < Register::kMaxNumAllocatableRegisters; ++i) {
-            if (output == NULL || !output->IsRegister() ||
-                output->index() != i) {
-              LiveRange* range = FixedLiveRangeFor(i);
-              range->AddUseInterval(curr_position,
-                                    curr_position.InstructionEnd(),
-                                    zone());
+          for (int i = 0; i < Register::kNumRegisters; ++i) {
+            if (Register::from_code(i).IsAllocatable()) {
+              if (output == NULL || !output->IsRegister() ||
+                  output->index() != i) {
+                LiveRange* range = FixedLiveRangeFor(i);
+                range->AddUseInterval(curr_position,
+                                      curr_position.InstructionEnd(), zone());
+              }
             }
           }
         }
 
         if (instr->ClobbersDoubleRegisters(isolate())) {
-          for (int i = 0; i < DoubleRegister::NumAllocatableRegisters(); ++i) {
-            if (output == NULL || !output->IsDoubleRegister() ||
-                output->index() != i) {
-              LiveRange* range = FixedDoubleLiveRangeFor(i);
-              range->AddUseInterval(curr_position,
-                                    curr_position.InstructionEnd(),
-                                    zone());
+          for (int i = 0; i < DoubleRegister::kMaxNumRegisters; ++i) {
+            if (DoubleRegister::from_code(i).IsAllocatable()) {
+              if (output == NULL || !output->IsDoubleRegister() ||
+                  output->index() != i) {
+                LiveRange* range = FixedDoubleLiveRangeFor(i);
+                range->AddUseInterval(curr_position,
+                                      curr_position.InstructionEnd(), zone());
+              }
             }
           }
         }
@@ -1069,11 +1072,9 @@ bool LAllocator::Allocate(LChunk* chunk) {
   DCHECK(chunk_ == NULL);
   chunk_ = static_cast<LPlatformChunk*>(chunk);
   assigned_registers_ =
-      new(chunk->zone()) BitVector(Register::NumAllocatableRegisters(),
-                                   chunk->zone());
-  assigned_double_registers_ =
-      new(chunk->zone()) BitVector(DoubleRegister::NumAllocatableRegisters(),
-                                   chunk->zone());
+      new (chunk->zone()) BitVector(Register::kNumRegisters, chunk->zone());
+  assigned_double_registers_ = new (chunk->zone())
+      BitVector(DoubleRegister::kMaxNumRegisters, chunk->zone());
   MeetRegisterConstraints();
   if (!AllocationOk()) return false;
   ResolvePhis();
@@ -1460,7 +1461,10 @@ void LAllocator::PopulatePointerMaps() {
 
 void LAllocator::AllocateGeneralRegisters() {
   LAllocatorPhase phase("L_Allocate general registers", this);
-  num_registers_ = Register::NumAllocatableRegisters();
+  num_registers_ =
+      RegisterConfiguration::ArchDefault()->num_allocatable_general_registers();
+  allocatable_register_codes_ =
+      RegisterConfiguration::ArchDefault()->allocatable_general_codes();
   mode_ = GENERAL_REGISTERS;
   AllocateRegisters();
 }
@@ -1468,7 +1472,10 @@ void LAllocator::AllocateGeneralRegisters() {
 
 void LAllocator::AllocateDoubleRegisters() {
   LAllocatorPhase phase("L_Allocate double registers", this);
-  num_registers_ = DoubleRegister::NumAllocatableRegisters();
+  num_registers_ =
+      RegisterConfiguration::ArchDefault()->num_allocatable_double_registers();
+  allocatable_register_codes_ =
+      RegisterConfiguration::ArchDefault()->allocatable_double_codes();
   mode_ = DOUBLE_REGISTERS;
   AllocateRegisters();
 }
@@ -1492,7 +1499,7 @@ void LAllocator::AllocateRegisters() {
   DCHECK(inactive_live_ranges_.is_empty());
 
   if (mode_ == DOUBLE_REGISTERS) {
-    for (int i = 0; i < DoubleRegister::NumAllocatableRegisters(); ++i) {
+    for (int i = 0; i < fixed_double_live_ranges_.length(); ++i) {
       LiveRange* current = fixed_double_live_ranges_.at(i);
       if (current != NULL) {
         AddToInactive(current);
@@ -1586,9 +1593,9 @@ void LAllocator::AllocateRegisters() {
 
 const char* LAllocator::RegisterName(int allocation_index) {
   if (mode_ == GENERAL_REGISTERS) {
-    return Register::AllocationIndexToString(allocation_index);
+    return Register::from_code(allocation_index).ToString();
   } else {
-    return DoubleRegister::AllocationIndexToString(allocation_index);
+    return DoubleRegister::from_code(allocation_index).ToString();
   }
 }
 
@@ -1750,16 +1757,12 @@ void LAllocator::InactiveToActive(LiveRange* range) {
 }
 
 
-// TryAllocateFreeReg and AllocateBlockedReg assume this
-// when allocating local arrays.
-STATIC_ASSERT(DoubleRegister::kMaxNumAllocatableRegisters >=
-              Register::kMaxNumAllocatableRegisters);
-
-
 bool LAllocator::TryAllocateFreeReg(LiveRange* current) {
-  LifetimePosition free_until_pos[DoubleRegister::kMaxNumAllocatableRegisters];
+  DCHECK(DoubleRegister::kMaxNumRegisters >= Register::kNumRegisters);
+
+  LifetimePosition free_until_pos[DoubleRegister::kMaxNumRegisters];
 
-  for (int i = 0; i < num_registers_; i++) {
+  for (int i = 0; i < DoubleRegister::kMaxNumRegisters; i++) {
     free_until_pos[i] = LifetimePosition::MaxPosition();
   }
 
@@ -1800,10 +1803,11 @@ bool LAllocator::TryAllocateFreeReg(LiveRange* current) {
   }
 
   // Find the register which stays free for the longest time.
-  int reg = 0;
+  int reg = allocatable_register_codes_[0];
   for (int i = 1; i < RegisterCount(); ++i) {
-    if (free_until_pos[i].Value() > free_until_pos[reg].Value()) {
-      reg = i;
+    int code = allocatable_register_codes_[i];
+    if (free_until_pos[code].Value() > free_until_pos[reg].Value()) {
+      reg = code;
     }
   }
 
@@ -1845,10 +1849,10 @@ void LAllocator::AllocateBlockedReg(LiveRange* current) {
   }
 
 
-  LifetimePosition use_pos[DoubleRegister::kMaxNumAllocatableRegisters];
-  LifetimePosition block_pos[DoubleRegister::kMaxNumAllocatableRegisters];
+  LifetimePosition use_pos[DoubleRegister::kMaxNumRegisters];
+  LifetimePosition block_pos[DoubleRegister::kMaxNumRegisters];
 
-  for (int i = 0; i < num_registers_; i++) {
+  for (int i = 0; i < DoubleRegister::kMaxNumRegisters; i++) {
     use_pos[i] = block_pos[i] = LifetimePosition::MaxPosition();
   }
 
@@ -1883,10 +1887,11 @@ void LAllocator::AllocateBlockedReg(LiveRange* current) {
     }
   }
 
-  int reg = 0;
+  int reg = allocatable_register_codes_[0];
   for (int i = 1; i < RegisterCount(); ++i) {
-    if (use_pos[i].Value() > use_pos[reg].Value()) {
-      reg = i;
+    int code = allocatable_register_codes_[i];
+    if (use_pos[code].Value() > use_pos[reg].Value()) {
+      reg = code;
     }
   }
 
index 7c947724509da266c0dd342f1f53d20073cacce4..476f6f45c08ab3b2047539b03c043cf8159f4572 100644 (file)
@@ -520,9 +520,8 @@ class LAllocator BASE_EMBEDDED {
   ZoneList<LiveRange*> live_ranges_;
 
   // Lists of live ranges
-  EmbeddedVector<LiveRange*, Register::kMaxNumAllocatableRegisters>
-      fixed_live_ranges_;
-  EmbeddedVector<LiveRange*, DoubleRegister::kMaxNumAllocatableRegisters>
+  EmbeddedVector<LiveRange*, Register::kNumRegisters> fixed_live_ranges_;
+  EmbeddedVector<LiveRange*, DoubleRegister::kMaxNumRegisters>
       fixed_double_live_ranges_;
   ZoneList<LiveRange*> unhandled_live_ranges_;
   ZoneList<LiveRange*> active_live_ranges_;
@@ -536,6 +535,7 @@ class LAllocator BASE_EMBEDDED {
 
   RegisterKind mode_;
   int num_registers_;
+  const int* allocatable_register_codes_;
 
   BitVector* assigned_registers_;
   BitVector* assigned_double_registers_;
index 7d37532ace71140d61bf42f20937aac91ac3088d..bc48a0a16389e3f505ebba26fba867726f45e271 100644 (file)
@@ -56,24 +56,22 @@ void LOperand::PrintTo(StringStream* stream) {
           break;
         case LUnallocated::FIXED_REGISTER: {
           int reg_index = unalloc->fixed_register_index();
-          if (reg_index < 0 ||
-              reg_index >= Register::kMaxNumAllocatableRegisters) {
+          if (reg_index < 0 || reg_index >= Register::kNumRegisters) {
             stream->Add("(=invalid_reg#%d)", reg_index);
           } else {
             const char* register_name =
-                Register::AllocationIndexToString(reg_index);
+                Register::from_code(reg_index).ToString();
             stream->Add("(=%s)", register_name);
           }
           break;
         }
         case LUnallocated::FIXED_DOUBLE_REGISTER: {
           int reg_index = unalloc->fixed_register_index();
-          if (reg_index < 0 ||
-              reg_index >= DoubleRegister::kMaxNumAllocatableRegisters) {
+          if (reg_index < 0 || reg_index >= DoubleRegister::kMaxNumRegisters) {
             stream->Add("(=invalid_double_reg#%d)", reg_index);
           } else {
             const char* double_register_name =
-                DoubleRegister::AllocationIndexToString(reg_index);
+                DoubleRegister::from_code(reg_index).ToString();
             stream->Add("(=%s)", double_register_name);
           }
           break;
@@ -106,21 +104,19 @@ void LOperand::PrintTo(StringStream* stream) {
       break;
     case REGISTER: {
       int reg_index = index();
-      if (reg_index < 0 || reg_index >= Register::kMaxNumAllocatableRegisters) {
+      if (reg_index < 0 || reg_index >= Register::kNumRegisters) {
         stream->Add("(=invalid_reg#%d|R)", reg_index);
       } else {
-        stream->Add("[%s|R]", Register::AllocationIndexToString(reg_index));
+        stream->Add("[%s|R]", Register::from_code(reg_index).ToString());
       }
       break;
     }
     case DOUBLE_REGISTER: {
       int reg_index = index();
-      if (reg_index < 0 ||
-          reg_index >= DoubleRegister::kMaxNumAllocatableRegisters) {
+      if (reg_index < 0 || reg_index >= DoubleRegister::kMaxNumRegisters) {
         stream->Add("(=invalid_double_reg#%d|R)", reg_index);
       } else {
-        stream->Add("[%s|R]",
-                    DoubleRegister::AllocationIndexToString(reg_index));
+        stream->Add("[%s|R]", DoubleRegister::from_code(reg_index).ToString());
       }
       break;
     }
index f4bddf54613731d9d5a002e09412bf3c62fd1ef3..8e7a1f5e9167bb14b6c8e2d9d64f1c406797012c 100644 (file)
@@ -84,36 +84,6 @@ bool Operand::is_reg() const {
 }
 
 
-int Register::NumAllocatableRegisters() {
-    return kMaxNumAllocatableRegisters;
-}
-
-
-int DoubleRegister::NumRegisters() {
-    return FPURegister::kMaxNumRegisters;
-}
-
-
-int DoubleRegister::NumAllocatableRegisters() {
-    return FPURegister::kMaxNumAllocatableRegisters;
-}
-
-
-int DoubleRegister::NumAllocatableAliasedRegisters() {
-  return NumAllocatableRegisters();
-}
-
-
-int FPURegister::ToAllocationIndex(FPURegister reg) {
-  DCHECK(reg.code() % 2 == 0);
-  DCHECK(reg.code() / 2 < kMaxNumAllocatableRegisters);
-  DCHECK(reg.is_valid());
-  DCHECK(!reg.is(kDoubleRegZero));
-  DCHECK(!reg.is(kLithiumScratchDouble));
-  return (reg.code() / 2);
-}
-
-
 // -----------------------------------------------------------------------------
 // RelocInfo.
 
index 7fa4d5d66a5c2fe2c97f67c480811c189c6e99d0..87abbe1b4d1ea6ba01a2d7f697d5042baa7bb73c 100644 (file)
@@ -64,28 +64,6 @@ static unsigned CpuFeaturesImpliedByCompiler() {
 }
 
 
-const char* DoubleRegister::AllocationIndexToString(int index) {
-  DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
-  const char* const names[] = {
-    "f0",
-    "f2",
-    "f4",
-    "f6",
-    "f8",
-    "f10",
-    "f12",
-    "f14",
-    "f16",
-    "f18",
-    "f20",
-    "f22",
-    "f24",
-    "f26"
-  };
-  return names[index];
-}
-
-
 void CpuFeatures::ProbeImpl(bool cross_compile) {
   supported_ |= CpuFeaturesImpliedByCompiler();
 
@@ -250,31 +228,31 @@ MemOperand::MemOperand(Register rm, int32_t unit, int32_t multiplier,
 static const int kNegOffset = 0x00008000;
 // addiu(sp, sp, 4) aka Pop() operation or part of Pop(r)
 // operations as post-increment of sp.
-const Instr kPopInstruction = ADDIU | (kRegister_sp_Code << kRsShift)
-      | (kRegister_sp_Code << kRtShift)
-      | (kPointerSize & kImm16Mask);  // NOLINT
+const Instr kPopInstruction = ADDIU | (Register::kCode_sp << kRsShift) |
+                              (Register::kCode_sp << kRtShift) |
+                              (kPointerSize & kImm16Mask);  // NOLINT
 // addiu(sp, sp, -4) part of Push(r) operation as pre-decrement of sp.
-const Instr kPushInstruction = ADDIU | (kRegister_sp_Code << kRsShift)
-      | (kRegister_sp_Code << kRtShift)
-      | (-kPointerSize & kImm16Mask);  // NOLINT
+const Instr kPushInstruction = ADDIU | (Register::kCode_sp << kRsShift) |
+                               (Register::kCode_sp << kRtShift) |
+                               (-kPointerSize & kImm16Mask);  // NOLINT
 // sw(r, MemOperand(sp, 0))
-const Instr kPushRegPattern = SW | (kRegister_sp_Code << kRsShift)
-      | (0 & kImm16Mask);  // NOLINT
+const Instr kPushRegPattern =
+    SW | (Register::kCode_sp << kRsShift) | (0 & kImm16Mask);  // NOLINT
 //  lw(r, MemOperand(sp, 0))
-const Instr kPopRegPattern = LW | (kRegister_sp_Code << kRsShift)
-      | (0 & kImm16Mask);  // NOLINT
+const Instr kPopRegPattern =
+    LW | (Register::kCode_sp << kRsShift) | (0 & kImm16Mask);  // NOLINT
 
-const Instr kLwRegFpOffsetPattern = LW | (kRegister_fp_Code << kRsShift)
-      | (0 & kImm16Mask);  // NOLINT
+const Instr kLwRegFpOffsetPattern =
+    LW | (Register::kCode_fp << kRsShift) | (0 & kImm16Mask);  // NOLINT
 
-const Instr kSwRegFpOffsetPattern = SW | (kRegister_fp_Code << kRsShift)
-      | (0 & kImm16Mask);  // NOLINT
+const Instr kSwRegFpOffsetPattern =
+    SW | (Register::kCode_fp << kRsShift) | (0 & kImm16Mask);  // NOLINT
 
-const Instr kLwRegFpNegOffsetPattern = LW | (kRegister_fp_Code << kRsShift)
-      | (kNegOffset & kImm16Mask);  // NOLINT
+const Instr kLwRegFpNegOffsetPattern = LW | (Register::kCode_fp << kRsShift) |
+                                       (kNegOffset & kImm16Mask);  // NOLINT
 
-const Instr kSwRegFpNegOffsetPattern = SW | (kRegister_fp_Code << kRsShift)
-      | (kNegOffset & kImm16Mask);  // NOLINT
+const Instr kSwRegFpNegOffsetPattern = SW | (Register::kCode_fp << kRsShift) |
+                                       (kNegOffset & kImm16Mask);  // NOLINT
 // A mask for the Rt register for push, pop, lw, sw instructions.
 const Instr kRtMask = kRtFieldMask;
 const Instr kLwSwInstrTypeMask = 0xffe00000;
@@ -334,21 +312,21 @@ void Assembler::CodeTargetAlign() {
 
 Register Assembler::GetRtReg(Instr instr) {
   Register rt;
-  rt.code_ = (instr & kRtFieldMask) >> kRtShift;
+  rt.reg_code = (instr & kRtFieldMask) >> kRtShift;
   return rt;
 }
 
 
 Register Assembler::GetRsReg(Instr instr) {
   Register rs;
-  rs.code_ = (instr & kRsFieldMask) >> kRsShift;
+  rs.reg_code = (instr & kRsFieldMask) >> kRsShift;
   return rs;
 }
 
 
 Register Assembler::GetRdReg(Instr instr) {
   Register rd;
-  rd.code_ = (instr & kRdFieldMask) >> kRdShift;
+  rd.reg_code = (instr & kRdFieldMask) >> kRdShift;
   return rd;
 }
 
@@ -1942,14 +1920,14 @@ void Assembler::movn(Register rd, Register rs, Register rt) {
 
 void Assembler::movt(Register rd, Register rs, uint16_t cc) {
   Register rt;
-  rt.code_ = (cc & 0x0007) << 2 | 1;
+  rt.reg_code = (cc & 0x0007) << 2 | 1;
   GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVCI);
 }
 
 
 void Assembler::movf(Register rd, Register rs, uint16_t cc) {
   Register rt;
-  rt.code_ = (cc & 0x0007) << 2 | 0;
+  rt.reg_code = (cc & 0x0007) << 2 | 0;
   GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVCI);
 }
 
@@ -2233,7 +2211,7 @@ void Assembler::movz_d(FPURegister fd, FPURegister fs, Register rt) {
 void Assembler::movt_s(FPURegister fd, FPURegister fs, uint16_t cc) {
   DCHECK(IsMipsArchVariant(kMips32r2));
   FPURegister ft;
-  ft.code_ = (cc & 0x0007) << 2 | 1;
+  ft.reg_code = (cc & 0x0007) << 2 | 1;
   GenInstrRegister(COP1, S, ft, fs, fd, MOVF);
 }
 
@@ -2241,7 +2219,7 @@ void Assembler::movt_s(FPURegister fd, FPURegister fs, uint16_t cc) {
 void Assembler::movt_d(FPURegister fd, FPURegister fs, uint16_t cc) {
   DCHECK(IsMipsArchVariant(kMips32r2));
   FPURegister ft;
-  ft.code_ = (cc & 0x0007) << 2 | 1;
+  ft.reg_code = (cc & 0x0007) << 2 | 1;
   GenInstrRegister(COP1, D, ft, fs, fd, MOVF);
 }
 
@@ -2249,7 +2227,7 @@ void Assembler::movt_d(FPURegister fd, FPURegister fs, uint16_t cc) {
 void Assembler::movf_s(FPURegister fd, FPURegister fs, uint16_t cc) {
   DCHECK(IsMipsArchVariant(kMips32r2));
   FPURegister ft;
-  ft.code_ = (cc & 0x0007) << 2 | 0;
+  ft.reg_code = (cc & 0x0007) << 2 | 0;
   GenInstrRegister(COP1, S, ft, fs, fd, MOVF);
 }
 
@@ -2257,7 +2235,7 @@ void Assembler::movf_s(FPURegister fd, FPURegister fs, uint16_t cc) {
 void Assembler::movf_d(FPURegister fd, FPURegister fs, uint16_t cc) {
   DCHECK(IsMipsArchVariant(kMips32r2));
   FPURegister ft;
-  ft.code_ = (cc & 0x0007) << 2 | 0;
+  ft.reg_code = (cc & 0x0007) << 2 | 0;
   GenInstrRegister(COP1, D, ft, fs, fd, MOVF);
 }
 
index c47f6d3abe2760997039c195e584ce6276a9440d..53fc8315d241e59b5c2754a58c0127f27df5d11a 100644 (file)
 namespace v8 {
 namespace internal {
 
+// clang-format off
+#define GENERAL_REGISTERS(V)                              \
+  V(zero_reg)  V(at)  V(v0)  V(v1)  V(a0)  V(a1)  V(a2)  V(a3)  \
+  V(t0)  V(t1)  V(t2)  V(t3)  V(t4)  V(t5)  V(t6)  V(t7)  \
+  V(s0)  V(s1)  V(s2)  V(s3)  V(s4)  V(s5)  V(s6)  V(s7)  V(t8)  V(t9) \
+  V(k0)  V(k1)  V(gp)  V(sp)  V(fp)  V(ra)
+
+#define ALLOCATABLE_GENERAL_REGISTERS(V) \
+  V(v0)  V(v1)  V(a0)  V(a1)  V(a2)  V(a3) \
+  V(t0)  V(t1)  V(t2)  V(t3)  V(t4)  V(t5)  V(t6) V(s7)
+
+#define DOUBLE_REGISTERS(V)                               \
+  V(f0)  V(f1)  V(f2)  V(f3)  V(f4)  V(f5)  V(f6)  V(f7)  \
+  V(f8)  V(f9)  V(f10) V(f11) V(f12) V(f13) V(f14) V(f15) \
+  V(f16) V(f17) V(f18) V(f19) V(f20) V(f21) V(f22) V(f23) \
+  V(f24) V(f25) V(f26) V(f27) V(f28) V(f29) V(f30) V(f31)
+
+#define ALLOCATABLE_DOUBLE_REGISTERS(V)                   \
+  V(f0)  V(f2)  V(f4)  V(f6)  V(f8)  V(f10) V(f12) V(f14) \
+  V(f16) V(f18) V(f20) V(f22) V(f24) V(f26)
+// clang-format on
+
 // CPU Registers.
 //
 // 1) We would prefer to use an enum, but enum values are assignment-
@@ -72,13 +94,19 @@ namespace internal {
 // -----------------------------------------------------------------------------
 // Implementation of Register and FPURegister.
 
-// Core register.
 struct Register {
-  static const int kNumRegisters = v8::internal::kNumRegisters;
-  static const int kMaxNumAllocatableRegisters = 14;  // v0 through t6 and cp.
-  static const int kSizeInBytes = 4;
   static const int kCpRegister = 23;  // cp (s7) is the 23rd register.
 
+  enum Code {
+#define REGISTER_CODE(R) kCode_##R,
+    GENERAL_REGISTERS(REGISTER_CODE)
+#undef REGISTER_CODE
+        kAfterLast,
+    kCode_no_reg = -1
+  };
+
+  static const int kNumRegisters = Code::kAfterLast;
+
 #if defined(V8_TARGET_LITTLE_ENDIAN)
   static const int kMantissaOffset = 0;
   static const int kExponentOffset = 4;
@@ -89,117 +117,37 @@ struct Register {
 #error Unknown endianness
 #endif
 
-  inline static int NumAllocatableRegisters();
-
-  static int ToAllocationIndex(Register reg) {
-    DCHECK((reg.code() - 2) < (kMaxNumAllocatableRegisters - 1) ||
-           reg.is(from_code(kCpRegister)));
-    return reg.is(from_code(kCpRegister)) ?
-           kMaxNumAllocatableRegisters - 1 :  // Return last index for 'cp'.
-           reg.code() - 2;  // zero_reg and 'at' are skipped.
-  }
-
-  static Register FromAllocationIndex(int index) {
-    DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
-    return index == kMaxNumAllocatableRegisters - 1 ?
-           from_code(kCpRegister) :  // Last index is always the 'cp' register.
-           from_code(index + 2);  // zero_reg and 'at' are skipped.
-  }
-
-  static const char* AllocationIndexToString(int index) {
-    DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
-    const char* const names[] = {
-      "v0",
-      "v1",
-      "a0",
-      "a1",
-      "a2",
-      "a3",
-      "t0",
-      "t1",
-      "t2",
-      "t3",
-      "t4",
-      "t5",
-      "t6",
-      "s7",
-    };
-    return names[index];
-  }
 
   static Register from_code(int code) {
-    Register r = { code };
+    DCHECK(code >= 0);
+    DCHECK(code < kNumRegisters);
+    Register r = {code};
     return r;
   }
-
-  bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
-  bool is(Register reg) const { return code_ == reg.code_; }
+  const char* ToString();
+  bool IsAllocatable() const;
+  bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; }
+  bool is(Register reg) const { return reg_code == reg.reg_code; }
   int code() const {
     DCHECK(is_valid());
-    return code_;
+    return reg_code;
   }
   int bit() const {
     DCHECK(is_valid());
-    return 1 << code_;
+    return 1 << reg_code;
   }
 
   // Unfortunately we can't make this private in a struct.
-  int code_;
+  int reg_code;
 };
 
-#define REGISTER(N, C) \
-  const int kRegister_ ## N ## _Code = C; \
-  const Register N = { C }
-
-REGISTER(no_reg, -1);
-// Always zero.
-REGISTER(zero_reg, 0);
-// at: Reserved for synthetic instructions.
-REGISTER(at, 1);
-// v0, v1: Used when returning multiple values from subroutines.
-REGISTER(v0, 2);
-REGISTER(v1, 3);
-// a0 - a4: Used to pass non-FP parameters.
-REGISTER(a0, 4);
-REGISTER(a1, 5);
-REGISTER(a2, 6);
-REGISTER(a3, 7);
-// t0 - t9: Can be used without reservation, act as temporary registers and are
-// allowed to be destroyed by subroutines.
-REGISTER(t0, 8);
-REGISTER(t1, 9);
-REGISTER(t2, 10);
-REGISTER(t3, 11);
-REGISTER(t4, 12);
-REGISTER(t5, 13);
-REGISTER(t6, 14);
-REGISTER(t7, 15);
-// s0 - s7: Subroutine register variables. Subroutines that write to these
-// registers must restore their values before exiting so that the caller can
-// expect the values to be preserved.
-REGISTER(s0, 16);
-REGISTER(s1, 17);
-REGISTER(s2, 18);
-REGISTER(s3, 19);
-REGISTER(s4, 20);
-REGISTER(s5, 21);
-REGISTER(s6, 22);
-REGISTER(s7, 23);
-REGISTER(t8, 24);
-REGISTER(t9, 25);
-// k0, k1: Reserved for system calls and interrupt handlers.
-REGISTER(k0, 26);
-REGISTER(k1, 27);
-// gp: Reserved.
-REGISTER(gp, 28);
-// sp: Stack pointer.
-REGISTER(sp, 29);
-// fp: Frame pointer.
-REGISTER(fp, 30);
-// ra: Return address pointer.
-REGISTER(ra, 31);
-
-#undef REGISTER
+// s7: context register
+// s3: lithium scratch
+// s4: lithium scratch2
+#define DECLARE_REGISTER(R) const Register R = {Register::kCode_##R};
+GENERAL_REGISTERS(DECLARE_REGISTER)
+#undef DECLARE_REGISTER
+const Register no_reg = {Register::kCode_no_reg};
 
 
 int ToNumber(Register reg);
@@ -207,75 +155,70 @@ int ToNumber(Register reg);
 Register ToRegister(int num);
 
 // Coprocessor register.
-struct FPURegister {
-  static const int kMaxNumRegisters = v8::internal::kNumFPURegisters;
-
-  // TODO(plind): Warning, inconsistent numbering here. kNumFPURegisters refers
-  // to number of 32-bit FPU regs, but kNumAllocatableRegisters refers to
-  // number of Double regs (64-bit regs, or FPU-reg-pairs).
+struct DoubleRegister {
+  enum Code {
+#define REGISTER_CODE(R) kCode_##R,
+    DOUBLE_REGISTERS(REGISTER_CODE)
+#undef REGISTER_CODE
+        kAfterLast,
+    kCode_no_reg = -1
+  };
 
-  // A few double registers are reserved: one as a scratch register and one to
-  // hold 0.0.
-  //  f28: 0.0
-  //  f30: scratch register.
-  static const int kNumReservedRegisters = 2;
-  static const int kMaxNumAllocatableRegisters = kMaxNumRegisters / 2 -
-      kNumReservedRegisters;
+  static const int kMaxNumRegisters = Code::kAfterLast;
 
   inline static int NumRegisters();
-  inline static int NumAllocatableRegisters();
-
-  // TODO(turbofan): Proper support for float32.
-  inline static int NumAllocatableAliasedRegisters();
 
-  inline static int ToAllocationIndex(FPURegister reg);
-  static const char* AllocationIndexToString(int index);
-
-  static FPURegister FromAllocationIndex(int index) {
-    DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
-    return from_code(index * 2);
-  }
-
-  static FPURegister from_code(int code) {
-    FPURegister r = { code };
-    return r;
-  }
+  // TODO(plind): Warning, inconsistent numbering here. kNumFPURegisters refers
+  // to number of 32-bit FPU regs, but kNumAllocatableRegisters refers to
+  // number of Double regs (64-bit regs, or FPU-reg-pairs).
 
-  bool is_valid() const { return 0 <= code_ && code_ < kMaxNumRegisters ; }
-  bool is(FPURegister creg) const { return code_ == creg.code_; }
-  FPURegister low() const {
+  const char* ToString();
+  bool IsAllocatable() const;
+  bool is_valid() const { return 0 <= reg_code && reg_code < kMaxNumRegisters; }
+  bool is(DoubleRegister reg) const { return reg_code == reg.reg_code; }
+  DoubleRegister low() const {
     // Find low reg of a Double-reg pair, which is the reg itself.
-    DCHECK(code_ % 2 == 0);  // Specified Double reg must be even.
-    FPURegister reg;
-    reg.code_ = code_;
+    DCHECK(reg_code % 2 == 0);  // Specified Double reg must be even.
+    DoubleRegister reg;
+    reg.reg_code = reg_code;
     DCHECK(reg.is_valid());
     return reg;
   }
-  FPURegister high() const {
+  DoubleRegister high() const {
     // Find high reg of a Doubel-reg pair, which is reg + 1.
-    DCHECK(code_ % 2 == 0);  // Specified Double reg must be even.
-    FPURegister reg;
-    reg.code_ = code_ + 1;
+    DCHECK(reg_code % 2 == 0);  // Specified Double reg must be even.
+    DoubleRegister reg;
+    reg.reg_code = reg_code + 1;
     DCHECK(reg.is_valid());
     return reg;
   }
 
   int code() const {
     DCHECK(is_valid());
-    return code_;
+    return reg_code;
   }
   int bit() const {
     DCHECK(is_valid());
-    return 1 << code_;
+    return 1 << reg_code;
+  }
+
+  static DoubleRegister from_code(int code) {
+    DoubleRegister r = {code};
+    return r;
   }
   void setcode(int f) {
-    code_ = f;
+    reg_code = f;
     DCHECK(is_valid());
   }
   // Unfortunately we can't make this private in a struct.
-  int code_;
+  int reg_code;
 };
 
+// A few double registers are reserved: one as a scratch register and one to
+// hold 0.0.
+//  f28: 0.0
+//  f30: scratch register.
+
 // V8 now supports the O32 ABI, and the FPU Registers are organized as 32
 // 32-bit registers, f0 through f31. When used as 'double' they are used
 // in pairs, starting with the even numbered register. So a double operation
@@ -285,43 +228,43 @@ struct FPURegister {
 // but it is not in common use. Someday we will want to support this in v8.)
 
 // For O32 ABI, Floats and Doubles refer to same set of 32 32-bit registers.
-typedef FPURegister DoubleRegister;
-typedef FPURegister FloatRegister;
-
-const FPURegister no_freg = { -1 };
-
-const FPURegister f0 = { 0 };  // Return value in hard float mode.
-const FPURegister f1 = { 1 };
-const FPURegister f2 = { 2 };
-const FPURegister f3 = { 3 };
-const FPURegister f4 = { 4 };
-const FPURegister f5 = { 5 };
-const FPURegister f6 = { 6 };
-const FPURegister f7 = { 7 };
-const FPURegister f8 = { 8 };
-const FPURegister f9 = { 9 };
-const FPURegister f10 = { 10 };
-const FPURegister f11 = { 11 };
-const FPURegister f12 = { 12 };  // Arg 0 in hard float mode.
-const FPURegister f13 = { 13 };
-const FPURegister f14 = { 14 };  // Arg 1 in hard float mode.
-const FPURegister f15 = { 15 };
-const FPURegister f16 = { 16 };
-const FPURegister f17 = { 17 };
-const FPURegister f18 = { 18 };
-const FPURegister f19 = { 19 };
-const FPURegister f20 = { 20 };
-const FPURegister f21 = { 21 };
-const FPURegister f22 = { 22 };
-const FPURegister f23 = { 23 };
-const FPURegister f24 = { 24 };
-const FPURegister f25 = { 25 };
-const FPURegister f26 = { 26 };
-const FPURegister f27 = { 27 };
-const FPURegister f28 = { 28 };
-const FPURegister f29 = { 29 };
-const FPURegister f30 = { 30 };
-const FPURegister f31 = { 31 };
+typedef DoubleRegister FPURegister;
+typedef DoubleRegister FloatRegister;
+
+const DoubleRegister no_freg = {-1};
+
+const DoubleRegister f0 = {0};  // Return value in hard float mode.
+const DoubleRegister f1 = {1};
+const DoubleRegister f2 = {2};
+const DoubleRegister f3 = {3};
+const DoubleRegister f4 = {4};
+const DoubleRegister f5 = {5};
+const DoubleRegister f6 = {6};
+const DoubleRegister f7 = {7};
+const DoubleRegister f8 = {8};
+const DoubleRegister f9 = {9};
+const DoubleRegister f10 = {10};
+const DoubleRegister f11 = {11};
+const DoubleRegister f12 = {12};  // Arg 0 in hard float mode.
+const DoubleRegister f13 = {13};
+const DoubleRegister f14 = {14};  // Arg 1 in hard float mode.
+const DoubleRegister f15 = {15};
+const DoubleRegister f16 = {16};
+const DoubleRegister f17 = {17};
+const DoubleRegister f18 = {18};
+const DoubleRegister f19 = {19};
+const DoubleRegister f20 = {20};
+const DoubleRegister f21 = {21};
+const DoubleRegister f22 = {22};
+const DoubleRegister f23 = {23};
+const DoubleRegister f24 = {24};
+const DoubleRegister f25 = {25};
+const DoubleRegister f26 = {26};
+const DoubleRegister f27 = {27};
+const DoubleRegister f28 = {28};
+const DoubleRegister f29 = {29};
+const DoubleRegister f30 = {30};
+const DoubleRegister f31 = {31};
 
 // Register aliases.
 // cp is assumed to be a callee saved register.
@@ -341,22 +284,22 @@ const FPURegister f31 = { 31 };
 // FPU (coprocessor 1) control registers.
 // Currently only FCSR (#31) is implemented.
 struct FPUControlRegister {
-  bool is_valid() const { return code_ == kFCSRRegister; }
-  bool is(FPUControlRegister creg) const { return code_ == creg.code_; }
+  bool is_valid() const { return reg_code == kFCSRRegister; }
+  bool is(FPUControlRegister creg) const { return reg_code == creg.reg_code; }
   int code() const {
     DCHECK(is_valid());
-    return code_;
+    return reg_code;
   }
   int bit() const {
     DCHECK(is_valid());
-    return 1 << code_;
+    return 1 << reg_code;
   }
   void setcode(int f) {
-    code_ = f;
+    reg_code = f;
     DCHECK(is_valid());
   }
   // Unfortunately we can't make this private in a struct.
-  int code_;
+  int reg_code;
 };
 
 const FPUControlRegister no_fpucreg = { kInvalidFPUControlRegister };
index 974692495a24e9d31fd0c166576b80fb8a9c10c6..10cab306a29d2ca3c24d008ba3acd2ae96f81138 100644 (file)
@@ -5,6 +5,7 @@
 #include "src/codegen.h"
 #include "src/deoptimizer.h"
 #include "src/full-codegen/full-codegen.h"
+#include "src/register-configuration.h"
 #include "src/safepoint-table.h"
 
 namespace v8 {
@@ -88,7 +89,7 @@ void Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) {
   }
   input_->SetRegister(sp.code(), reinterpret_cast<intptr_t>(frame->sp()));
   input_->SetRegister(fp.code(), reinterpret_cast<intptr_t>(frame->fp()));
-  for (int i = 0; i < DoubleRegister::NumAllocatableRegisters(); i++) {
+  for (int i = 0; i < DoubleRegister::kMaxNumRegisters; i++) {
     input_->SetDoubleRegister(i, 0.0);
   }
 
@@ -139,14 +140,15 @@ void Deoptimizer::TableEntryGenerator::Generate() {
   RegList restored_regs = kJSCallerSaved | kCalleeSaved;
   RegList saved_regs = restored_regs | sp.bit() | ra.bit();
 
-  const int kDoubleRegsSize =
-      kDoubleSize * FPURegister::kMaxNumAllocatableRegisters;
+  const int kDoubleRegsSize = kDoubleSize * DoubleRegister::kMaxNumRegisters;
 
   // Save all FPU registers before messing with them.
   __ Subu(sp, sp, Operand(kDoubleRegsSize));
-  for (int i = 0; i < FPURegister::kMaxNumAllocatableRegisters; ++i) {
-    FPURegister fpu_reg = FPURegister::FromAllocationIndex(i);
-    int offset = i * kDoubleSize;
+  const RegisterConfiguration* config = RegisterConfiguration::ArchDefault();
+  for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
+    int code = config->GetAllocatableDoubleCode(i);
+    const DoubleRegister fpu_reg = DoubleRegister::from_code(code);
+    int offset = code * kDoubleSize;
     __ sdc1(fpu_reg, MemOperand(sp, offset));
   }
 
@@ -215,9 +217,10 @@ void Deoptimizer::TableEntryGenerator::Generate() {
   int double_regs_offset = FrameDescription::double_registers_offset();
   // Copy FPU registers to
   // double_registers_[DoubleRegister::kNumAllocatableRegisters]
-  for (int i = 0; i < FPURegister::NumAllocatableRegisters(); ++i) {
-    int dst_offset = i * kDoubleSize + double_regs_offset;
-    int src_offset = i * kDoubleSize + kNumberOfRegisters * kPointerSize;
+  for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
+    int code = config->GetAllocatableDoubleCode(i);
+    int dst_offset = code * kDoubleSize + double_regs_offset;
+    int src_offset = code * kDoubleSize + kNumberOfRegisters * kPointerSize;
     __ ldc1(f0, MemOperand(sp, src_offset));
     __ sdc1(f0, MemOperand(a1, dst_offset));
   }
@@ -284,9 +287,10 @@ void Deoptimizer::TableEntryGenerator::Generate() {
   __ BranchShort(&outer_push_loop, lt, t0, Operand(a1));
 
   __ lw(a1, MemOperand(a0, Deoptimizer::input_offset()));
-  for (int i = 0; i < FPURegister::kMaxNumAllocatableRegisters; ++i) {
-    const FPURegister fpu_reg = FPURegister::FromAllocationIndex(i);
-    int src_offset = i * kDoubleSize + double_regs_offset;
+  for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
+    int code = config->GetAllocatableDoubleCode(i);
+    const DoubleRegister fpu_reg = DoubleRegister::from_code(code);
+    int src_offset = code * kDoubleSize + double_regs_offset;
     __ ldc1(fpu_reg, MemOperand(a1, src_offset));
   }
 
index 9e45868f8ed67c69814b94a765a303adeba2eafd..36eb821c0aa0cebd59ee6bc9f6e6b9fa5a8fde8f 100644 (file)
@@ -96,7 +96,7 @@ void LCodeGen::SaveCallerDoubles() {
   BitVector* doubles = chunk()->allocated_double_registers();
   BitVector::Iterator save_iterator(doubles);
   while (!save_iterator.Done()) {
-    __ sdc1(DoubleRegister::FromAllocationIndex(save_iterator.Current()),
+    __ sdc1(DoubleRegister::from_code(save_iterator.Current()),
             MemOperand(sp, count * kDoubleSize));
     save_iterator.Advance();
     count++;
@@ -112,7 +112,7 @@ void LCodeGen::RestoreCallerDoubles() {
   BitVector::Iterator save_iterator(doubles);
   int count = 0;
   while (!save_iterator.Done()) {
-    __ ldc1(DoubleRegister::FromAllocationIndex(save_iterator.Current()),
+    __ ldc1(DoubleRegister::from_code(save_iterator.Current()),
             MemOperand(sp, count * kDoubleSize));
     save_iterator.Advance();
     count++;
@@ -403,12 +403,12 @@ bool LCodeGen::GenerateSafepointTable() {
 
 
 Register LCodeGen::ToRegister(int index) const {
-  return Register::FromAllocationIndex(index);
+  return Register::from_code(index);
 }
 
 
 DoubleRegister LCodeGen::ToDoubleRegister(int index) const {
-  return DoubleRegister::FromAllocationIndex(index);
+  return DoubleRegister::from_code(index);
 }
 
 
index 42ecab4b8e3c205724760b97bf5bfbd269c0d7a8..cafa4cfdbc22858b42e26a15b36f161aef7722dc 100644 (file)
@@ -451,14 +451,13 @@ LPlatformChunk* LChunkBuilder::Build() {
 
 
 LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
-  return new(zone()) LUnallocated(LUnallocated::FIXED_REGISTER,
-                                  Register::ToAllocationIndex(reg));
+  return new (zone()) LUnallocated(LUnallocated::FIXED_REGISTER, reg.code());
 }
 
 
 LUnallocated* LChunkBuilder::ToUnallocated(DoubleRegister reg) {
-  return new(zone()) LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER,
-                                  DoubleRegister::ToAllocationIndex(reg));
+  return new (zone())
+      LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER, reg.code());
 }
 
 
index e66fad9092c7a1e62f74c35e44308a29d7573a28..6b078f2f2ae1499b1175e4a9019e245eebebe3d3 100644 (file)
@@ -14,6 +14,7 @@
 #include "src/cpu-profiler.h"
 #include "src/debug/debug.h"
 #include "src/mips/macro-assembler-mips.h"
+#include "src/register-configuration.h"
 #include "src/runtime/runtime.h"
 
 namespace v8 {
@@ -147,7 +148,7 @@ MemOperand MacroAssembler::SafepointRegisterSlot(Register reg) {
 MemOperand MacroAssembler::SafepointRegistersAndDoublesSlot(Register reg) {
   UNIMPLEMENTED_MIPS();
   // General purpose registers are pushed last on the stack.
-  int doubles_size = FPURegister::NumAllocatableRegisters() * kDoubleSize;
+  int doubles_size = DoubleRegister::kMaxNumRegisters * kDoubleSize;
   int register_offset = SafepointRegisterStackIndex(reg.code()) * kPointerSize;
   return MemOperand(sp, doubles_size + register_offset);
 }
@@ -3682,7 +3683,7 @@ void MacroAssembler::CopyFields(Register dst,
   // Find a temp register in temps list.
   for (int i = 0; i < kNumRegisters; i++) {
     if ((temps & (1 << i)) != 0) {
-      tmp.code_ = i;
+      tmp.reg_code = i;
       break;
     }
   }
@@ -5771,8 +5772,10 @@ Register GetRegisterThatIsNotOneOf(Register reg1,
   if (reg5.is_valid()) regs |= reg5.bit();
   if (reg6.is_valid()) regs |= reg6.bit();
 
-  for (int i = 0; i < Register::NumAllocatableRegisters(); i++) {
-    Register candidate = Register::FromAllocationIndex(i);
+  const RegisterConfiguration* config = RegisterConfiguration::ArchDefault();
+  for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
+    int code = config->GetAllocatableGeneralCode(i);
+    Register candidate = Register::from_code(code);
     if (regs & candidate.bit()) continue;
     return candidate;
   }
index 1b715a3a732892a98111aceb0e7d594c1060314b..a6a474e7bcad445349ce13d6f45e8f929b534cfa 100644 (file)
@@ -13,17 +13,17 @@ namespace v8 {
 namespace internal {
 
 // Give alias names to registers for calling conventions.
-const Register kReturnRegister0 = {kRegister_v0_Code};
-const Register kReturnRegister1 = {kRegister_v1_Code};
-const Register kJSFunctionRegister = {kRegister_a1_Code};
+const Register kReturnRegister0 = {Register::kCode_v0};
+const Register kReturnRegister1 = {Register::kCode_v1};
+const Register kJSFunctionRegister = {Register::kCode_a1};
 const Register kContextRegister = {Register::kCpRegister};
-const Register kInterpreterAccumulatorRegister = {kRegister_v0_Code};
-const Register kInterpreterRegisterFileRegister = {kRegister_t3_Code};
-const Register kInterpreterBytecodeOffsetRegister = {kRegister_t4_Code};
-const Register kInterpreterBytecodeArrayRegister = {kRegister_t5_Code};
-const Register kInterpreterDispatchTableRegister = {kRegister_t6_Code};
-const Register kRuntimeCallFunctionRegister = {kRegister_a1_Code};
-const Register kRuntimeCallArgCountRegister = {kRegister_a0_Code};
+const Register kInterpreterAccumulatorRegister = {Register::kCode_v0};
+const Register kInterpreterRegisterFileRegister = {Register::kCode_t3};
+const Register kInterpreterBytecodeOffsetRegister = {Register::kCode_t4};
+const Register kInterpreterBytecodeArrayRegister = {Register::kCode_t5};
+const Register kInterpreterDispatchTableRegister = {Register::kCode_t6};
+const Register kRuntimeCallFunctionRegister = {Register::kCode_a1};
+const Register kRuntimeCallArgCountRegister = {Register::kCode_a0};
 
 // Forward declaration.
 class JumpTarget;
index 16ca33a9f3440c6de6a40f2d266c2eecf21af456..cb41c9f65a48ab98cc1c97ddd1ec41fcaa9d2047 100644 (file)
@@ -84,36 +84,6 @@ bool Operand::is_reg() const {
 }
 
 
-int Register::NumAllocatableRegisters() {
-    return kMaxNumAllocatableRegisters;
-}
-
-
-int DoubleRegister::NumRegisters() {
-    return FPURegister::kMaxNumRegisters;
-}
-
-
-int DoubleRegister::NumAllocatableRegisters() {
-    return FPURegister::kMaxNumAllocatableRegisters;
-}
-
-
-int DoubleRegister::NumAllocatableAliasedRegisters() {
-  return NumAllocatableRegisters();
-}
-
-
-int FPURegister::ToAllocationIndex(FPURegister reg) {
-  DCHECK(reg.code() % 2 == 0);
-  DCHECK(reg.code() / 2 < kMaxNumAllocatableRegisters);
-  DCHECK(reg.is_valid());
-  DCHECK(!reg.is(kDoubleRegZero));
-  DCHECK(!reg.is(kLithiumScratchDouble));
-  return (reg.code() / 2);
-}
-
-
 // -----------------------------------------------------------------------------
 // RelocInfo.
 
index cb5e164ff9ce3fae978c5250fbffacea82da7d68..d5acd8d95560f73e7f0d8a62a4ffe87b705a2f9b 100644 (file)
@@ -64,28 +64,6 @@ static unsigned CpuFeaturesImpliedByCompiler() {
 }
 
 
-const char* DoubleRegister::AllocationIndexToString(int index) {
-  DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
-  const char* const names[] = {
-    "f0",
-    "f2",
-    "f4",
-    "f6",
-    "f8",
-    "f10",
-    "f12",
-    "f14",
-    "f16",
-    "f18",
-    "f20",
-    "f22",
-    "f24",
-    "f26"
-  };
-  return names[index];
-}
-
-
 void CpuFeatures::ProbeImpl(bool cross_compile) {
   supported_ |= CpuFeaturesImpliedByCompiler();
 
@@ -229,31 +207,31 @@ MemOperand::MemOperand(Register rm, int32_t unit, int32_t multiplier,
 static const int kNegOffset = 0x00008000;
 // daddiu(sp, sp, 8) aka Pop() operation or part of Pop(r)
 // operations as post-increment of sp.
-const Instr kPopInstruction = DADDIU | (kRegister_sp_Code << kRsShift)
-      | (kRegister_sp_Code << kRtShift)
-      | (kPointerSize & kImm16Mask);  // NOLINT
+const Instr kPopInstruction = DADDIU | (Register::kCode_sp << kRsShift) |
+                              (Register::kCode_sp << kRtShift) |
+                              (kPointerSize & kImm16Mask);  // NOLINT
 // daddiu(sp, sp, -8) part of Push(r) operation as pre-decrement of sp.
-const Instr kPushInstruction = DADDIU | (kRegister_sp_Code << kRsShift)
-      | (kRegister_sp_Code << kRtShift)
-      | (-kPointerSize & kImm16Mask);  // NOLINT
+const Instr kPushInstruction = DADDIU | (Register::kCode_sp << kRsShift) |
+                               (Register::kCode_sp << kRtShift) |
+                               (-kPointerSize & kImm16Mask);  // NOLINT
 // sd(r, MemOperand(sp, 0))
-const Instr kPushRegPattern = SD | (kRegister_sp_Code << kRsShift)
-      |  (0 & kImm16Mask);  // NOLINT
+const Instr kPushRegPattern =
+    SD | (Register::kCode_sp << kRsShift) | (0 & kImm16Mask);  // NOLINT
 //  ld(r, MemOperand(sp, 0))
-const Instr kPopRegPattern = LD | (kRegister_sp_Code << kRsShift)
-      |  (0 & kImm16Mask);  // NOLINT
+const Instr kPopRegPattern =
+    LD | (Register::kCode_sp << kRsShift) | (0 & kImm16Mask);  // NOLINT
 
-const Instr kLwRegFpOffsetPattern = LW | (kRegister_fp_Code << kRsShift)
-      |  (0 & kImm16Mask);  // NOLINT
+const Instr kLwRegFpOffsetPattern =
+    LW | (Register::kCode_fp << kRsShift) | (0 & kImm16Mask);  // NOLINT
 
-const Instr kSwRegFpOffsetPattern = SW | (kRegister_fp_Code << kRsShift)
-      |  (0 & kImm16Mask);  // NOLINT
+const Instr kSwRegFpOffsetPattern =
+    SW | (Register::kCode_fp << kRsShift) | (0 & kImm16Mask);  // NOLINT
 
-const Instr kLwRegFpNegOffsetPattern = LW | (kRegister_fp_Code << kRsShift)
-      |  (kNegOffset & kImm16Mask);  // NOLINT
+const Instr kLwRegFpNegOffsetPattern = LW | (Register::kCode_fp << kRsShift) |
+                                       (kNegOffset & kImm16Mask);  // NOLINT
 
-const Instr kSwRegFpNegOffsetPattern = SW | (kRegister_fp_Code << kRsShift)
-      |  (kNegOffset & kImm16Mask);  // NOLINT
+const Instr kSwRegFpNegOffsetPattern = SW | (Register::kCode_fp << kRsShift) |
+                                       (kNegOffset & kImm16Mask);  // NOLINT
 // A mask for the Rt register for push, pop, lw, sw instructions.
 const Instr kRtMask = kRtFieldMask;
 const Instr kLwSwInstrTypeMask = 0xffe00000;
@@ -314,21 +292,21 @@ void Assembler::CodeTargetAlign() {
 
 Register Assembler::GetRtReg(Instr instr) {
   Register rt;
-  rt.code_ = (instr & kRtFieldMask) >> kRtShift;
+  rt.reg_code = (instr & kRtFieldMask) >> kRtShift;
   return rt;
 }
 
 
 Register Assembler::GetRsReg(Instr instr) {
   Register rs;
-  rs.code_ = (instr & kRsFieldMask) >> kRsShift;
+  rs.reg_code = (instr & kRsFieldMask) >> kRsShift;
   return rs;
 }
 
 
 Register Assembler::GetRdReg(Instr instr) {
   Register rd;
-  rd.code_ = (instr & kRdFieldMask) >> kRdShift;
+  rd.reg_code = (instr & kRdFieldMask) >> kRdShift;
   return rd;
 }
 
@@ -2211,14 +2189,14 @@ void Assembler::movn(Register rd, Register rs, Register rt) {
 
 void Assembler::movt(Register rd, Register rs, uint16_t cc) {
   Register rt;
-  rt.code_ = (cc & 0x0007) << 2 | 1;
+  rt.reg_code = (cc & 0x0007) << 2 | 1;
   GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVCI);
 }
 
 
 void Assembler::movf(Register rd, Register rs, uint16_t cc) {
   Register rt;
-  rt.code_ = (cc & 0x0007) << 2 | 0;
+  rt.reg_code = (cc & 0x0007) << 2 | 0;
   GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVCI);
 }
 
@@ -2520,7 +2498,7 @@ void Assembler::movz_d(FPURegister fd, FPURegister fs, Register rt) {
 void Assembler::movt_s(FPURegister fd, FPURegister fs, uint16_t cc) {
   DCHECK(kArchVariant == kMips64r2);
   FPURegister ft;
-  ft.code_ = (cc & 0x0007) << 2 | 1;
+  ft.reg_code = (cc & 0x0007) << 2 | 1;
   GenInstrRegister(COP1, S, ft, fs, fd, MOVF);
 }
 
@@ -2528,7 +2506,7 @@ void Assembler::movt_s(FPURegister fd, FPURegister fs, uint16_t cc) {
 void Assembler::movt_d(FPURegister fd, FPURegister fs, uint16_t cc) {
   DCHECK(kArchVariant == kMips64r2);
   FPURegister ft;
-  ft.code_ = (cc & 0x0007) << 2 | 1;
+  ft.reg_code = (cc & 0x0007) << 2 | 1;
   GenInstrRegister(COP1, D, ft, fs, fd, MOVF);
 }
 
@@ -2536,7 +2514,7 @@ void Assembler::movt_d(FPURegister fd, FPURegister fs, uint16_t cc) {
 void Assembler::movf_s(FPURegister fd, FPURegister fs, uint16_t cc) {
   DCHECK(kArchVariant == kMips64r2);
   FPURegister ft;
-  ft.code_ = (cc & 0x0007) << 2 | 0;
+  ft.reg_code = (cc & 0x0007) << 2 | 0;
   GenInstrRegister(COP1, S, ft, fs, fd, MOVF);
 }
 
@@ -2544,7 +2522,7 @@ void Assembler::movf_s(FPURegister fd, FPURegister fs, uint16_t cc) {
 void Assembler::movf_d(FPURegister fd, FPURegister fs, uint16_t cc) {
   DCHECK(kArchVariant == kMips64r2);
   FPURegister ft;
-  ft.code_ = (cc & 0x0007) << 2 | 0;
+  ft.reg_code = (cc & 0x0007) << 2 | 0;
   GenInstrRegister(COP1, D, ft, fs, fd, MOVF);
 }
 
index 2036aa796397f05009804038c2e504659fa24b8e..074827e53e5ad6084a6045c2c26c27512b46509d 100644 (file)
 namespace v8 {
 namespace internal {
 
+// clang-format off
+#define GENERAL_REGISTERS(V)                              \
+  V(zero_reg)  V(at)  V(v0)  V(v1)  V(a0)  V(a1)  V(a2)  V(a3)  \
+  V(a4)  V(a5)  V(a6)  V(a7)  V(t0)  V(t1)  V(t2)  V(t3)  \
+  V(s0)  V(s1)  V(s2)  V(s3)  V(s4)  V(s5)  V(s6)  V(s7)  V(t8)  V(t9) \
+  V(k0)  V(k1)  V(gp)  V(sp)  V(fp)  V(ra)
+
+#define ALLOCATABLE_GENERAL_REGISTERS(V) \
+  V(v0)  V(v1)  V(a0)  V(a1)  V(a2)  V(a3) \
+  V(a4)  V(a5)  V(a6)  V(a7)  V(t0)  V(t1)  V(t2) V(s7)
+
+#define DOUBLE_REGISTERS(V)                               \
+  V(f0)  V(f1)  V(f2)  V(f3)  V(f4)  V(f5)  V(f6)  V(f7)  \
+  V(f8)  V(f9)  V(f10) V(f11) V(f12) V(f13) V(f14) V(f15) \
+  V(f16) V(f17) V(f18) V(f19) V(f20) V(f21) V(f22) V(f23) \
+  V(f24) V(f25) V(f26) V(f27) V(f28) V(f29) V(f30) V(f31)
+
+#define ALLOCATABLE_DOUBLE_REGISTERS(V)                   \
+  V(f0)  V(f2)  V(f4)  V(f6)  V(f8)  V(f10) V(f12) V(f14) \
+  V(f16) V(f18) V(f20) V(f22) V(f24) V(f26)
+// clang-format on
+
 // CPU Registers.
 //
 // 1) We would prefer to use an enum, but enum values are assignment-
@@ -72,124 +94,50 @@ namespace internal {
 // -----------------------------------------------------------------------------
 // Implementation of Register and FPURegister.
 
-// Core register.
 struct Register {
-  static const int kNumRegisters = v8::internal::kNumRegisters;
-  static const int kMaxNumAllocatableRegisters = 14;  // v0 through t2 and cp.
-  static const int kSizeInBytes = 8;
   static const int kCpRegister = 23;  // cp (s7) is the 23rd register.
 
-  inline static int NumAllocatableRegisters();
-
-  static int ToAllocationIndex(Register reg) {
-    DCHECK((reg.code() - 2) < (kMaxNumAllocatableRegisters - 1) ||
-           reg.is(from_code(kCpRegister)));
-    return reg.is(from_code(kCpRegister)) ?
-           kMaxNumAllocatableRegisters - 1 :  // Return last index for 'cp'.
-           reg.code() - 2;  // zero_reg and 'at' are skipped.
-  }
-
-  static Register FromAllocationIndex(int index) {
-    DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
-    return index == kMaxNumAllocatableRegisters - 1 ?
-           from_code(kCpRegister) :  // Last index is always the 'cp' register.
-           from_code(index + 2);  // zero_reg and 'at' are skipped.
-  }
-
-  static const char* AllocationIndexToString(int index) {
-    DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
-    const char* const names[] = {
-      "v0",
-      "v1",
-      "a0",
-      "a1",
-      "a2",
-      "a3",
-      "a4",
-      "a5",
-      "a6",
-      "a7",
-      "t0",
-      "t1",
-      "t2",
-      "s7",
-    };
-    return names[index];
-  }
+  enum Code {
+#define REGISTER_CODE(R) kCode_##R,
+    GENERAL_REGISTERS(REGISTER_CODE)
+#undef REGISTER_CODE
+        kAfterLast,
+    kCode_no_reg = -1
+  };
+
+  static const int kNumRegisters = Code::kAfterLast;
 
   static Register from_code(int code) {
+    DCHECK(code >= 0);
+    DCHECK(code < kNumRegisters);
     Register r = { code };
     return r;
   }
 
-  bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
-  bool is(Register reg) const { return code_ == reg.code_; }
+  const char* ToString();
+  bool IsAllocatable() const;
+  bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; }
+  bool is(Register reg) const { return reg_code == reg.reg_code; }
   int code() const {
     DCHECK(is_valid());
-    return code_;
+    return reg_code;
   }
   int bit() const {
     DCHECK(is_valid());
-    return 1 << code_;
+    return 1 << reg_code;
   }
 
   // Unfortunately we can't make this private in a struct.
-  int code_;
+  int reg_code;
 };
 
-#define REGISTER(N, C) \
-  const int kRegister_ ## N ## _Code = C; \
-  const Register N = { C }
-
-REGISTER(no_reg, -1);
-// Always zero.
-REGISTER(zero_reg, 0);
-// at: Reserved for synthetic instructions.
-REGISTER(at, 1);
-// v0, v1: Used when returning multiple values from subroutines.
-REGISTER(v0, 2);
-REGISTER(v1, 3);
-// a0 - a4: Used to pass non-FP parameters.
-REGISTER(a0, 4);
-REGISTER(a1, 5);
-REGISTER(a2, 6);
-REGISTER(a3, 7);
-// a4 - a7 t0 - t3: Can be used without reservation, act as temporary registers
-// and are allowed to be destroyed by subroutines.
-REGISTER(a4, 8);
-REGISTER(a5, 9);
-REGISTER(a6, 10);
-REGISTER(a7, 11);
-REGISTER(t0, 12);
-REGISTER(t1, 13);
-REGISTER(t2, 14);
-REGISTER(t3, 15);
-// s0 - s7: Subroutine register variables. Subroutines that write to these
-// registers must restore their values before exiting so that the caller can
-// expect the values to be preserved.
-REGISTER(s0, 16);
-REGISTER(s1, 17);
-REGISTER(s2, 18);
-REGISTER(s3, 19);
-REGISTER(s4, 20);
-REGISTER(s5, 21);
-REGISTER(s6, 22);
-REGISTER(s7, 23);
-REGISTER(t8, 24);
-REGISTER(t9, 25);
-// k0, k1: Reserved for system calls and interrupt handlers.
-REGISTER(k0, 26);
-REGISTER(k1, 27);
-// gp: Reserved.
-REGISTER(gp, 28);
-// sp: Stack pointer.
-REGISTER(sp, 29);
-// fp: Frame pointer.
-REGISTER(fp, 30);
-// ra: Return address pointer.
-REGISTER(ra, 31);
-
-#undef REGISTER
+// s7: context register
+// s3: lithium scratch
+// s4: lithium scratch2
+#define DECLARE_REGISTER(R) const Register R = {Register::kCode_##R};
+GENERAL_REGISTERS(DECLARE_REGISTER)
+#undef DECLARE_REGISTER
+const Register no_reg = {Register::kCode_no_reg};
 
 
 int ToNumber(Register reg);
@@ -197,77 +145,72 @@ int ToNumber(Register reg);
 Register ToRegister(int num);
 
 // Coprocessor register.
-struct FPURegister {
-  static const int kMaxNumRegisters = v8::internal::kNumFPURegisters;
-
-  // TODO(plind): Warning, inconsistent numbering here. kNumFPURegisters refers
-  // to number of 32-bit FPU regs, but kNumAllocatableRegisters refers to
-  // number of Double regs (64-bit regs, or FPU-reg-pairs).
+struct DoubleRegister {
+  enum Code {
+#define REGISTER_CODE(R) kCode_##R,
+    DOUBLE_REGISTERS(REGISTER_CODE)
+#undef REGISTER_CODE
+        kAfterLast,
+    kCode_no_reg = -1
+  };
 
-  // A few double registers are reserved: one as a scratch register and one to
-  // hold 0.0.
-  //  f28: 0.0
-  //  f30: scratch register.
-  static const int kNumReservedRegisters = 2;
-  static const int kMaxNumAllocatableRegisters = kMaxNumRegisters / 2 -
-      kNumReservedRegisters;
+  static const int kMaxNumRegisters = Code::kAfterLast;
 
   inline static int NumRegisters();
-  inline static int NumAllocatableRegisters();
-
-  // TODO(turbofan): Proper support for float32.
-  inline static int NumAllocatableAliasedRegisters();
-
-  inline static int ToAllocationIndex(FPURegister reg);
-  static const char* AllocationIndexToString(int index);
 
-  static FPURegister FromAllocationIndex(int index) {
-    DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
-    return from_code(index * 2);
-  }
-
-  static FPURegister from_code(int code) {
-    FPURegister r = { code };
-    return r;
-  }
+  // TODO(plind): Warning, inconsistent numbering here. kNumFPURegisters refers
+  // to number of 32-bit FPU regs, but kNumAllocatableRegisters refers to
+  // number of Double regs (64-bit regs, or FPU-reg-pairs).
 
-  bool is_valid() const { return 0 <= code_ && code_ < kMaxNumRegisters ; }
-  bool is(FPURegister creg) const { return code_ == creg.code_; }
-  FPURegister low() const {
+  const char* ToString();
+  bool IsAllocatable() const;
+  bool is_valid() const { return 0 <= reg_code && reg_code < kMaxNumRegisters; }
+  bool is(DoubleRegister reg) const { return reg_code == reg.reg_code; }
+  DoubleRegister low() const {
     // TODO(plind): Create DCHECK for FR=0 mode. This usage suspect for FR=1.
     // Find low reg of a Double-reg pair, which is the reg itself.
-    DCHECK(code_ % 2 == 0);  // Specified Double reg must be even.
-    FPURegister reg;
-    reg.code_ = code_;
+    DCHECK(reg_code % 2 == 0);  // Specified Double reg must be even.
+    DoubleRegister reg;
+    reg.reg_code = reg_code;
     DCHECK(reg.is_valid());
     return reg;
   }
-  FPURegister high() const {
+  DoubleRegister high() const {
     // TODO(plind): Create DCHECK for FR=0 mode. This usage illegal in FR=1.
     // Find high reg of a Doubel-reg pair, which is reg + 1.
-    DCHECK(code_ % 2 == 0);  // Specified Double reg must be even.
-    FPURegister reg;
-    reg.code_ = code_ + 1;
+    DCHECK(reg_code % 2 == 0);  // Specified Double reg must be even.
+    DoubleRegister reg;
+    reg.reg_code = reg_code + 1;
     DCHECK(reg.is_valid());
     return reg;
   }
 
   int code() const {
     DCHECK(is_valid());
-    return code_;
+    return reg_code;
   }
   int bit() const {
     DCHECK(is_valid());
-    return 1 << code_;
+    return 1 << reg_code;
+  }
+
+  static DoubleRegister from_code(int code) {
+    DoubleRegister r = {code};
+    return r;
   }
   void setcode(int f) {
-    code_ = f;
+    reg_code = f;
     DCHECK(is_valid());
   }
   // Unfortunately we can't make this private in a struct.
-  int code_;
+  int reg_code;
 };
 
+// A few double registers are reserved: one as a scratch register and one to
+// hold 0.0.
+//  f28: 0.0
+//  f30: scratch register.
+
 // V8 now supports the O32 ABI, and the FPU Registers are organized as 32
 // 32-bit registers, f0 through f31. When used as 'double' they are used
 // in pairs, starting with the even numbered register. So a double operation
@@ -277,43 +220,43 @@ struct FPURegister {
 // but it is not in common use. Someday we will want to support this in v8.)
 
 // For O32 ABI, Floats and Doubles refer to same set of 32 32-bit registers.
-typedef FPURegister DoubleRegister;
-typedef FPURegister FloatRegister;
-
-const FPURegister no_freg = { -1 };
-
-const FPURegister f0 = { 0 };  // Return value in hard float mode.
-const FPURegister f1 = { 1 };
-const FPURegister f2 = { 2 };
-const FPURegister f3 = { 3 };
-const FPURegister f4 = { 4 };
-const FPURegister f5 = { 5 };
-const FPURegister f6 = { 6 };
-const FPURegister f7 = { 7 };
-const FPURegister f8 = { 8 };
-const FPURegister f9 = { 9 };
-const FPURegister f10 = { 10 };
-const FPURegister f11 = { 11 };
-const FPURegister f12 = { 12 };  // Arg 0 in hard float mode.
-const FPURegister f13 = { 13 };
-const FPURegister f14 = { 14 };  // Arg 1 in hard float mode.
-const FPURegister f15 = { 15 };
-const FPURegister f16 = { 16 };
-const FPURegister f17 = { 17 };
-const FPURegister f18 = { 18 };
-const FPURegister f19 = { 19 };
-const FPURegister f20 = { 20 };
-const FPURegister f21 = { 21 };
-const FPURegister f22 = { 22 };
-const FPURegister f23 = { 23 };
-const FPURegister f24 = { 24 };
-const FPURegister f25 = { 25 };
-const FPURegister f26 = { 26 };
-const FPURegister f27 = { 27 };
-const FPURegister f28 = { 28 };
-const FPURegister f29 = { 29 };
-const FPURegister f30 = { 30 };
-const FPURegister f31 = { 31 };
+typedef DoubleRegister FPURegister;
+typedef DoubleRegister FloatRegister;
+
+const DoubleRegister no_freg = {-1};
+
+const DoubleRegister f0 = {0};  // Return value in hard float mode.
+const DoubleRegister f1 = {1};
+const DoubleRegister f2 = {2};
+const DoubleRegister f3 = {3};
+const DoubleRegister f4 = {4};
+const DoubleRegister f5 = {5};
+const DoubleRegister f6 = {6};
+const DoubleRegister f7 = {7};
+const DoubleRegister f8 = {8};
+const DoubleRegister f9 = {9};
+const DoubleRegister f10 = {10};
+const DoubleRegister f11 = {11};
+const DoubleRegister f12 = {12};  // Arg 0 in hard float mode.
+const DoubleRegister f13 = {13};
+const DoubleRegister f14 = {14};  // Arg 1 in hard float mode.
+const DoubleRegister f15 = {15};
+const DoubleRegister f16 = {16};
+const DoubleRegister f17 = {17};
+const DoubleRegister f18 = {18};
+const DoubleRegister f19 = {19};
+const DoubleRegister f20 = {20};
+const DoubleRegister f21 = {21};
+const DoubleRegister f22 = {22};
+const DoubleRegister f23 = {23};
+const DoubleRegister f24 = {24};
+const DoubleRegister f25 = {25};
+const DoubleRegister f26 = {26};
+const DoubleRegister f27 = {27};
+const DoubleRegister f28 = {28};
+const DoubleRegister f29 = {29};
+const DoubleRegister f30 = {30};
+const DoubleRegister f31 = {31};
 
 // Register aliases.
 // cp is assumed to be a callee saved register.
@@ -333,22 +276,22 @@ const FPURegister f31 = { 31 };
 // FPU (coprocessor 1) control registers.
 // Currently only FCSR (#31) is implemented.
 struct FPUControlRegister {
-  bool is_valid() const { return code_ == kFCSRRegister; }
-  bool is(FPUControlRegister creg) const { return code_ == creg.code_; }
+  bool is_valid() const { return reg_code == kFCSRRegister; }
+  bool is(FPUControlRegister creg) const { return reg_code == creg.reg_code; }
   int code() const {
     DCHECK(is_valid());
-    return code_;
+    return reg_code;
   }
   int bit() const {
     DCHECK(is_valid());
-    return 1 << code_;
+    return 1 << reg_code;
   }
   void setcode(int f) {
-    code_ = f;
+    reg_code = f;
     DCHECK(is_valid());
   }
   // Unfortunately we can't make this private in a struct.
-  int code_;
+  int reg_code;
 };
 
 const FPUControlRegister no_fpucreg = { kInvalidFPUControlRegister };
index 958951a948ea6f10214037c464e08781b3e4bf3e..9c047efcc908a49babd4d6ad49303aaa14a6773a 100644 (file)
@@ -5,6 +5,7 @@
 #include "src/codegen.h"
 #include "src/deoptimizer.h"
 #include "src/full-codegen/full-codegen.h"
+#include "src/register-configuration.h"
 #include "src/safepoint-table.h"
 
 namespace v8 {
@@ -88,7 +89,7 @@ void Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) {
   }
   input_->SetRegister(sp.code(), reinterpret_cast<intptr_t>(frame->sp()));
   input_->SetRegister(fp.code(), reinterpret_cast<intptr_t>(frame->fp()));
-  for (int i = 0; i < DoubleRegister::NumAllocatableRegisters(); i++) {
+  for (int i = 0; i < DoubleRegister::kMaxNumRegisters; i++) {
     input_->SetDoubleRegister(i, 0.0);
   }
 
@@ -139,14 +140,15 @@ void Deoptimizer::TableEntryGenerator::Generate() {
   RegList restored_regs = kJSCallerSaved | kCalleeSaved;
   RegList saved_regs = restored_regs | sp.bit() | ra.bit();
 
-  const int kDoubleRegsSize =
-      kDoubleSize * FPURegister::kMaxNumAllocatableRegisters;
+  const int kDoubleRegsSize = kDoubleSize * DoubleRegister::kMaxNumRegisters;
 
   // Save all FPU registers before messing with them.
   __ Dsubu(sp, sp, Operand(kDoubleRegsSize));
-  for (int i = 0; i < FPURegister::kMaxNumAllocatableRegisters; ++i) {
-    FPURegister fpu_reg = FPURegister::FromAllocationIndex(i);
-    int offset = i * kDoubleSize;
+  const RegisterConfiguration* config = RegisterConfiguration::ArchDefault();
+  for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
+    int code = config->GetAllocatableDoubleCode(i);
+    const DoubleRegister fpu_reg = DoubleRegister::from_code(code);
+    int offset = code * kDoubleSize;
     __ sdc1(fpu_reg, MemOperand(sp, offset));
   }
 
@@ -221,9 +223,10 @@ void Deoptimizer::TableEntryGenerator::Generate() {
   int double_regs_offset = FrameDescription::double_registers_offset();
   // Copy FPU registers to
   // double_registers_[DoubleRegister::kNumAllocatableRegisters]
-  for (int i = 0; i < FPURegister::NumAllocatableRegisters(); ++i) {
-    int dst_offset = i * kDoubleSize + double_regs_offset;
-    int src_offset = i * kDoubleSize + kNumberOfRegisters * kPointerSize;
+  for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
+    int code = config->GetAllocatableDoubleCode(i);
+    int dst_offset = code * kDoubleSize + double_regs_offset;
+    int src_offset = code * kDoubleSize + kNumberOfRegisters * kPointerSize;
     __ ldc1(f0, MemOperand(sp, src_offset));
     __ sdc1(f0, MemOperand(a1, dst_offset));
   }
@@ -289,9 +292,10 @@ void Deoptimizer::TableEntryGenerator::Generate() {
   __ BranchShort(&outer_push_loop, lt, a4, Operand(a1));
 
   __ ld(a1, MemOperand(a0, Deoptimizer::input_offset()));
-  for (int i = 0; i < FPURegister::kMaxNumAllocatableRegisters; ++i) {
-    const FPURegister fpu_reg = FPURegister::FromAllocationIndex(i);
-    int src_offset = i * kDoubleSize + double_regs_offset;
+  for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
+    int code = config->GetAllocatableDoubleCode(i);
+    const DoubleRegister fpu_reg = DoubleRegister::from_code(code);
+    int src_offset = code * kDoubleSize + double_regs_offset;
     __ ldc1(fpu_reg, MemOperand(a1, src_offset));
   }
 
index 4c76551138e0801aca4b23d10a913f44561e745a..22a06e8e120d2aee865791862929c04bdb772bcd 100644 (file)
@@ -71,7 +71,7 @@ void LCodeGen::SaveCallerDoubles() {
   BitVector* doubles = chunk()->allocated_double_registers();
   BitVector::Iterator save_iterator(doubles);
   while (!save_iterator.Done()) {
-    __ sdc1(DoubleRegister::FromAllocationIndex(save_iterator.Current()),
+    __ sdc1(DoubleRegister::from_code(save_iterator.Current()),
             MemOperand(sp, count * kDoubleSize));
     save_iterator.Advance();
     count++;
@@ -87,7 +87,7 @@ void LCodeGen::RestoreCallerDoubles() {
   BitVector::Iterator save_iterator(doubles);
   int count = 0;
   while (!save_iterator.Done()) {
-    __ ldc1(DoubleRegister::FromAllocationIndex(save_iterator.Current()),
+    __ ldc1(DoubleRegister::from_code(save_iterator.Current()),
             MemOperand(sp, count * kDoubleSize));
     save_iterator.Advance();
     count++;
@@ -386,12 +386,12 @@ bool LCodeGen::GenerateSafepointTable() {
 
 
 Register LCodeGen::ToRegister(int index) const {
-  return Register::FromAllocationIndex(index);
+  return Register::from_code(index);
 }
 
 
 DoubleRegister LCodeGen::ToDoubleRegister(int index) const {
-  return DoubleRegister::FromAllocationIndex(index);
+  return DoubleRegister::from_code(index);
 }
 
 
index 4f2f16152410792da707179b8b60dd61d77875ee..4595722fb4061775ec1b2a8bec98026ef36495e4 100644 (file)
@@ -451,14 +451,13 @@ LPlatformChunk* LChunkBuilder::Build() {
 
 
 LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
-  return new(zone()) LUnallocated(LUnallocated::FIXED_REGISTER,
-                                  Register::ToAllocationIndex(reg));
+  return new (zone()) LUnallocated(LUnallocated::FIXED_REGISTER, reg.code());
 }
 
 
 LUnallocated* LChunkBuilder::ToUnallocated(DoubleRegister reg) {
-  return new(zone()) LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER,
-                                  DoubleRegister::ToAllocationIndex(reg));
+  return new (zone())
+      LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER, reg.code());
 }
 
 
index 7a49ed0ba4a7107596ac980ce71ea607576e06cc..e071a777bbfb8066b75bc6c0d41941a25aca5c3c 100644 (file)
@@ -12,6 +12,7 @@
 #include "src/cpu-profiler.h"
 #include "src/debug/debug.h"
 #include "src/mips64/macro-assembler-mips64.h"
+#include "src/register-configuration.h"
 #include "src/runtime/runtime.h"
 
 namespace v8 {
@@ -149,7 +150,7 @@ MemOperand MacroAssembler::SafepointRegisterSlot(Register reg) {
 MemOperand MacroAssembler::SafepointRegistersAndDoublesSlot(Register reg) {
   UNIMPLEMENTED_MIPS();
   // General purpose registers are pushed last on the stack.
-  int doubles_size = FPURegister::NumAllocatableRegisters() * kDoubleSize;
+  int doubles_size = DoubleRegister::kMaxNumRegisters * kDoubleSize;
   int register_offset = SafepointRegisterStackIndex(reg.code()) * kPointerSize;
   return MemOperand(sp, doubles_size + register_offset);
 }
@@ -3731,7 +3732,7 @@ void MacroAssembler::CopyFields(Register dst,
   // Find a temp register in temps list.
   for (int i = 0; i < kNumRegisters; i++) {
     if ((temps & (1 << i)) != 0) {
-      tmp.code_ = i;
+      tmp.reg_code = i;
       break;
     }
   }
@@ -5964,8 +5965,10 @@ Register GetRegisterThatIsNotOneOf(Register reg1,
   if (reg5.is_valid()) regs |= reg5.bit();
   if (reg6.is_valid()) regs |= reg6.bit();
 
-  for (int i = 0; i < Register::NumAllocatableRegisters(); i++) {
-    Register candidate = Register::FromAllocationIndex(i);
+  const RegisterConfiguration* config = RegisterConfiguration::ArchDefault();
+  for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
+    int code = config->GetAllocatableGeneralCode(i);
+    Register candidate = Register::from_code(code);
     if (regs & candidate.bit()) continue;
     return candidate;
   }
index 3d1cbe35f21119323e39574babbb7c7eb9cc5227..f138179f39c1ff7dcef9dc8f7a4b852b7d0c2da3 100644 (file)
@@ -13,17 +13,17 @@ namespace v8 {
 namespace internal {
 
 // Give alias names to registers for calling conventions.
-const Register kReturnRegister0 = {kRegister_v0_Code};
-const Register kReturnRegister1 = {kRegister_v1_Code};
-const Register kJSFunctionRegister = {kRegister_a1_Code};
-const Register kContextRegister = {kRegister_s7_Code};
-const Register kInterpreterAccumulatorRegister = {kRegister_v0_Code};
-const Register kInterpreterRegisterFileRegister = {kRegister_a7_Code};
-const Register kInterpreterBytecodeOffsetRegister = {kRegister_t0_Code};
-const Register kInterpreterBytecodeArrayRegister = {kRegister_t1_Code};
-const Register kInterpreterDispatchTableRegister = {kRegister_t2_Code};
-const Register kRuntimeCallFunctionRegister = {kRegister_a1_Code};
-const Register kRuntimeCallArgCountRegister = {kRegister_a0_Code};
+const Register kReturnRegister0 = {Register::kCode_v0};
+const Register kReturnRegister1 = {Register::kCode_v1};
+const Register kJSFunctionRegister = {Register::kCode_a1};
+const Register kContextRegister = {Register::kCpRegister};
+const Register kInterpreterAccumulatorRegister = {Register::kCode_v0};
+const Register kInterpreterRegisterFileRegister = {Register::kCode_a7};
+const Register kInterpreterBytecodeOffsetRegister = {Register::kCode_t0};
+const Register kInterpreterBytecodeArrayRegister = {Register::kCode_t1};
+const Register kInterpreterDispatchTableRegister = {Register::kCode_t2};
+const Register kRuntimeCallFunctionRegister = {Register::kCode_a1};
+const Register kRuntimeCallArgCountRegister = {Register::kCode_a0};
 
 // Forward declaration.
 class JumpTarget;
index 3e88c961eef0756bc54e58bbae3d0a2076beebd2..626ae77ce298ffff423c05d6ada0aff2267857ba 100644 (file)
@@ -12162,7 +12162,7 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint(
 
         case Translation::DOUBLE_REGISTER: {
           int reg_code = iterator.Next();
-          os << "{input=" << DoubleRegister::AllocationIndexToString(reg_code)
+          os << "{input=" << DoubleRegister::from_code(reg_code).ToString()
              << "}";
           break;
         }
diff --git a/src/register-configuration.cc b/src/register-configuration.cc
new file mode 100644 (file)
index 0000000..9b1c951
--- /dev/null
@@ -0,0 +1,146 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/register-configuration.h"
+#include "src/globals.h"
+#include "src/macro-assembler.h"
+
+namespace v8 {
+namespace internal {
+
+namespace {
+
+#define REGISTER_COUNT(R) 1 +
+static const int kMaxAllocatableGeneralRegisterCount =
+    ALLOCATABLE_GENERAL_REGISTERS(REGISTER_COUNT)0;
+static const int kMaxAllocatableDoubleRegisterCount =
+    ALLOCATABLE_DOUBLE_REGISTERS(REGISTER_COUNT)0;
+
+static const char* const kGeneralRegisterNames[] = {
+#define REGISTER_NAME(R) #R,
+    GENERAL_REGISTERS(REGISTER_NAME)
+#undef REGISTER_NAME
+};
+
+static const char* const kDoubleRegisterNames[] = {
+#define REGISTER_NAME(R) #R,
+    DOUBLE_REGISTERS(REGISTER_NAME)
+#undef REGISTER_NAME
+};
+
+STATIC_ASSERT(RegisterConfiguration::kMaxGeneralRegisters >=
+              Register::kNumRegisters);
+STATIC_ASSERT(RegisterConfiguration::kMaxDoubleRegisters >=
+              DoubleRegister::kMaxNumRegisters);
+
+class ArchDefaultRegisterConfiguration : public RegisterConfiguration {
+ public:
+  ArchDefaultRegisterConfiguration()
+      : RegisterConfiguration(
+            Register::kNumRegisters, DoubleRegister::kMaxNumRegisters,
+#if V8_TARGET_ARCH_IA32
+            kMaxAllocatableGeneralRegisterCount,
+            kMaxAllocatableDoubleRegisterCount,
+            kMaxAllocatableDoubleRegisterCount,
+#elif V8_TARGET_ARCH_X87
+            kMaxAllocatableGeneralRegisterCount, 1, 1,
+#elif V8_TARGET_ARCH_X64
+            kMaxAllocatableGeneralRegisterCount,
+            kMaxAllocatableDoubleRegisterCount,
+            kMaxAllocatableDoubleRegisterCount,
+#elif V8_TARGET_ARCH_ARM
+            FLAG_enable_embedded_constant_pool
+                ? (kMaxAllocatableGeneralRegisterCount - 1)
+                : kMaxAllocatableGeneralRegisterCount,
+            CpuFeatures::IsSupported(VFP32DREGS)
+                ? kMaxAllocatableDoubleRegisterCount
+                : (ALLOCATABLE_NO_VFP32_DOUBLE_REGISTERS(REGISTER_COUNT)0),
+            ALLOCATABLE_NO_VFP32_DOUBLE_REGISTERS(REGISTER_COUNT)0,
+#elif V8_TARGET_ARCH_ARM64
+            kMaxAllocatableGeneralRegisterCount,
+            kMaxAllocatableDoubleRegisterCount,
+            kMaxAllocatableDoubleRegisterCount,
+#elif V8_TARGET_ARCH_MIPS
+            kMaxAllocatableGeneralRegisterCount,
+            kMaxAllocatableDoubleRegisterCount,
+            kMaxAllocatableDoubleRegisterCount,
+#elif V8_TARGET_ARCH_MIPS64
+            kMaxAllocatableGeneralRegisterCount,
+            kMaxAllocatableDoubleRegisterCount,
+            kMaxAllocatableDoubleRegisterCount,
+#else
+            GetAllocatableGeneralRegisterCount(),
+            GetAllocatableDoubleRegisterCount(),
+            GetAllocatableAliasedDoubleRegisterCount(),
+#endif
+            GetAllocatableGeneralCodes(), GetAllocatableDoubleCodes(),
+            kGeneralRegisterNames, kDoubleRegisterNames) {
+  }
+
+  const char* general_register_name_table_[Register::kNumRegisters];
+  const char* double_register_name_table_[DoubleRegister::kMaxNumRegisters];
+
+ private:
+  friend struct Register;
+  friend struct DoubleRegister;
+
+  static const int* GetAllocatableGeneralCodes() {
+#define REGISTER_CODE(R) Register::kCode_##R,
+    static const int general_codes[] = {
+        ALLOCATABLE_GENERAL_REGISTERS(REGISTER_CODE)};
+#undef REGISTER_CODE
+    return general_codes;
+  }
+
+  static const int* GetAllocatableDoubleCodes() {
+#define REGISTER_CODE(R) DoubleRegister::kCode_##R,
+    static const int double_codes[] = {
+        ALLOCATABLE_DOUBLE_REGISTERS(REGISTER_CODE)};
+#undef REGISTER_CODE
+    return double_codes;
+  }
+};
+
+
+static base::LazyInstance<ArchDefaultRegisterConfiguration>::type
+    kDefaultRegisterConfiguration = LAZY_INSTANCE_INITIALIZER;
+
+}  // namespace
+
+
+const RegisterConfiguration* RegisterConfiguration::ArchDefault() {
+  return &kDefaultRegisterConfiguration.Get();
+}
+
+RegisterConfiguration::RegisterConfiguration(
+    int num_general_registers, int num_double_registers,
+    int num_allocatable_general_registers, int num_allocatable_double_registers,
+    int num_allocatable_aliased_double_registers,
+    const int* allocatable_general_codes, const int* allocatable_double_codes,
+    const char* const* general_register_names,
+    const char* const* double_register_names)
+    : num_general_registers_(num_general_registers),
+      num_double_registers_(num_double_registers),
+      num_allocatable_general_registers_(num_allocatable_general_registers),
+      num_allocatable_double_registers_(num_allocatable_double_registers),
+      num_allocatable_aliased_double_registers_(
+          num_allocatable_aliased_double_registers),
+      allocatable_general_codes_mask_(0),
+      allocatable_double_codes_mask_(0),
+      allocatable_general_codes_(allocatable_general_codes),
+      allocatable_double_codes_(allocatable_double_codes),
+      general_register_names_(general_register_names),
+      double_register_names_(double_register_names) {
+  for (int i = 0; i < num_allocatable_general_registers_; ++i) {
+    allocatable_general_codes_mask_ |= (1 << allocatable_general_codes_[i]);
+  }
+  for (int i = 0; i < num_allocatable_double_registers_; ++i) {
+    allocatable_double_codes_mask_ |= (1 << allocatable_double_codes_[i]);
+  }
+}
+
+#undef REGISTER_COUNT
+
+}  // namespace internal
+}  // namespace v8
diff --git a/src/register-configuration.h b/src/register-configuration.h
new file mode 100644 (file)
index 0000000..f12bc7c
--- /dev/null
@@ -0,0 +1,88 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_COMPILER_REGISTER_CONFIGURATION_H_
+#define V8_COMPILER_REGISTER_CONFIGURATION_H_
+
+#include "src/base/macros.h"
+
+namespace v8 {
+namespace internal {
+
+// An architecture independent representation of the sets of registers available
+// for instruction creation.
+class RegisterConfiguration {
+ public:
+  // Architecture independent maxes.
+  static const int kMaxGeneralRegisters = 32;
+  static const int kMaxDoubleRegisters = 32;
+
+  static const RegisterConfiguration* ArchDefault();
+
+  RegisterConfiguration(int num_general_registers, int num_double_registers,
+                        int num_allocatable_general_registers,
+                        int num_allocatable_double_registers,
+                        int num_allocatable_aliased_double_registers,
+                        const int* allocatable_general_codes,
+                        const int* allocatable_double_codes,
+                        char const* const* general_names,
+                        char const* const* double_names);
+
+  int num_general_registers() const { return num_general_registers_; }
+  int num_double_registers() const { return num_double_registers_; }
+  int num_allocatable_general_registers() const {
+    return num_allocatable_general_registers_;
+  }
+  int num_allocatable_double_registers() const {
+    return num_allocatable_double_registers_;
+  }
+  // TODO(turbofan): This is a temporary work-around required because our
+  // register allocator does not yet support the aliasing of single/double
+  // registers on ARM.
+  int num_allocatable_aliased_double_registers() const {
+    return num_allocatable_aliased_double_registers_;
+  }
+  int32_t allocatable_general_codes_mask() const {
+    return allocatable_general_codes_mask_;
+  }
+  int32_t allocatable_double_codes_mask() const {
+    return allocatable_double_codes_mask_;
+  }
+  int GetAllocatableGeneralCode(int index) const {
+    return allocatable_general_codes_[index];
+  }
+  int GetAllocatableDoubleCode(int index) const {
+    return allocatable_double_codes_[index];
+  }
+  const char* GetGeneralRegisterName(int code) const {
+    return general_register_names_[code];
+  }
+  const char* GetDoubleRegisterName(int code) const {
+    return double_register_names_[code];
+  }
+  const int* allocatable_general_codes() const {
+    return allocatable_general_codes_;
+  }
+  const int* allocatable_double_codes() const {
+    return allocatable_double_codes_;
+  }
+
+ private:
+  const int num_general_registers_;
+  const int num_double_registers_;
+  int num_allocatable_general_registers_;
+  int num_allocatable_double_registers_;
+  int num_allocatable_aliased_double_registers_;
+  int32_t allocatable_general_codes_mask_;
+  int32_t allocatable_double_codes_mask_;
+  const int* allocatable_general_codes_;
+  const int* allocatable_double_codes_;
+  char const* const* general_register_names_;
+  char const* const* double_register_names_;
+};
+
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_COMPILER_REGISTER_CONFIGURATION_H_
index cb93ab878b9517a1348d32df1914fa9cff856f65..059b576beaa42d52765c8b383762199a0a14e392 100644 (file)
@@ -115,20 +115,6 @@ void CpuFeatures::PrintFeatures() {
 }
 
 
-// -----------------------------------------------------------------------------
-// Register constants.
-
-const int
-    Register::kRegisterCodeByAllocationIndex[kMaxNumAllocatableRegisters] = {
-  // rax, rbx, rdx, rcx, rsi, rdi, r8, r9, r11, r12, r14, r15
-  0, 3, 2, 1, 6, 7, 8, 9, 11, 12, 14, 15
-};
-
-const int Register::kAllocationIndexByRegisterCode[kNumRegisters] = {
-  0, 3, 2, 1, -1, -1, 4, 5, 6, 7, -1, 8, 9, -1, 10, 11
-};
-
-
 // -----------------------------------------------------------------------------
 // Implementation of Operand
 
index 47e4d2bddae310469a02e4a93c7e6681bbdad0ab..d5e855c8478c197b00e27b149ecbeea5aac9eb52 100644 (file)
@@ -47,6 +47,39 @@ namespace internal {
 
 // Utility functions
 
+#define GENERAL_REGISTERS(V) \
+  V(rax)                     \
+  V(rcx)                     \
+  V(rdx)                     \
+  V(rbx)                     \
+  V(rsp)                     \
+  V(rbp)                     \
+  V(rsi)                     \
+  V(rdi)                     \
+  V(r8)                      \
+  V(r9)                      \
+  V(r10)                     \
+  V(r11)                     \
+  V(r12)                     \
+  V(r13)                     \
+  V(r14)                     \
+  V(r15)
+
+#define ALLOCATABLE_GENERAL_REGISTERS(V) \
+  V(rax)                                 \
+  V(rbx)                                 \
+  V(rdx)                                 \
+  V(rcx)                                 \
+  V(rsi)                                 \
+  V(rdi)                                 \
+  V(r8)                                  \
+  V(r9)                                  \
+  V(r11)                                 \
+  V(r12)                                 \
+  V(r14)                                 \
+  V(r15)
+
+
 // CPU Registers.
 //
 // 1) We would prefer to use an enum, but enum values are assignment-
@@ -68,226 +101,153 @@ namespace internal {
 // mode. This way we get the compile-time error checking in debug mode
 // and best performance in optimized code.
 //
-
 struct Register {
-  // The non-allocatable registers are:
-  //  rsp - stack pointer
-  //  rbp - frame pointer
-  //  r10 - fixed scratch register
-  //  r13 - root register
-  static const int kMaxNumAllocatableRegisters = 12;
-  static int NumAllocatableRegisters() {
-    return kMaxNumAllocatableRegisters;
-  }
-  static const int kNumRegisters = 16;
-
-  static int ToAllocationIndex(Register reg) {
-    return kAllocationIndexByRegisterCode[reg.code()];
-  }
-
-  static Register FromAllocationIndex(int index) {
-    DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
-    Register result = { kRegisterCodeByAllocationIndex[index] };
-    return result;
-  }
+  enum Code {
+#define REGISTER_CODE(R) kCode_##R,
+    GENERAL_REGISTERS(REGISTER_CODE)
+#undef REGISTER_CODE
+        kAfterLast,
+    kCode_no_reg = -1
+  };
 
-  static const char* AllocationIndexToString(int index) {
-    DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
-    const char* const names[] = {
-      "rax",
-      "rbx",
-      "rdx",
-      "rcx",
-      "rsi",
-      "rdi",
-      "r8",
-      "r9",
-      "r11",
-      "r12",
-      "r14",
-      "r15"
-    };
-    return names[index];
-  }
+  static const int kNumRegisters = Code::kAfterLast;
 
   static Register from_code(int code) {
-    Register r = { code };
+    DCHECK(code >= 0);
+    DCHECK(code < kNumRegisters);
+    Register r = {code};
     return r;
   }
-  bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
-  bool is(Register reg) const { return code_ == reg.code_; }
-  // rax, rbx, rcx and rdx are byte registers, the rest are not.
-  bool is_byte_register() const { return code_ <= 3; }
+  const char* ToString();
+  bool IsAllocatable() const;
+  bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; }
+  bool is(Register reg) const { return reg_code == reg.reg_code; }
   int code() const {
     DCHECK(is_valid());
-    return code_;
+    return reg_code;
   }
   int bit() const {
-    return 1 << code_;
+    DCHECK(is_valid());
+    return 1 << reg_code;
   }
 
+  bool is_byte_register() const { return reg_code <= 3; }
   // Return the high bit of the register code as a 0 or 1.  Used often
   // when constructing the REX prefix byte.
-  int high_bit() const {
-    return code_ >> 3;
-  }
+  int high_bit() const { return reg_code >> 3; }
   // Return the 3 low bits of the register code.  Used when encoding registers
   // in modR/M, SIB, and opcode bytes.
-  int low_bits() const {
-    return code_ & 0x7;
-  }
+  int low_bits() const { return reg_code & 0x7; }
 
   // Unfortunately we can't make this private in a struct when initializing
   // by assignment.
-  int code_;
-
- private:
-  static const int kRegisterCodeByAllocationIndex[kMaxNumAllocatableRegisters];
-  static const int kAllocationIndexByRegisterCode[kNumRegisters];
+  int reg_code;
 };
 
-const int kRegister_rax_Code = 0;
-const int kRegister_rcx_Code = 1;
-const int kRegister_rdx_Code = 2;
-const int kRegister_rbx_Code = 3;
-const int kRegister_rsp_Code = 4;
-const int kRegister_rbp_Code = 5;
-const int kRegister_rsi_Code = 6;
-const int kRegister_rdi_Code = 7;
-const int kRegister_r8_Code = 8;
-const int kRegister_r9_Code = 9;
-const int kRegister_r10_Code = 10;
-const int kRegister_r11_Code = 11;
-const int kRegister_r12_Code = 12;
-const int kRegister_r13_Code = 13;
-const int kRegister_r14_Code = 14;
-const int kRegister_r15_Code = 15;
-const int kRegister_no_reg_Code = -1;
-
-const Register rax = { kRegister_rax_Code };
-const Register rcx = { kRegister_rcx_Code };
-const Register rdx = { kRegister_rdx_Code };
-const Register rbx = { kRegister_rbx_Code };
-const Register rsp = { kRegister_rsp_Code };
-const Register rbp = { kRegister_rbp_Code };
-const Register rsi = { kRegister_rsi_Code };
-const Register rdi = { kRegister_rdi_Code };
-const Register r8 = { kRegister_r8_Code };
-const Register r9 = { kRegister_r9_Code };
-const Register r10 = { kRegister_r10_Code };
-const Register r11 = { kRegister_r11_Code };
-const Register r12 = { kRegister_r12_Code };
-const Register r13 = { kRegister_r13_Code };
-const Register r14 = { kRegister_r14_Code };
-const Register r15 = { kRegister_r15_Code };
-const Register no_reg = { kRegister_no_reg_Code };
+
+#define DECLARE_REGISTER(R) const Register R = {Register::kCode_##R};
+GENERAL_REGISTERS(DECLARE_REGISTER)
+#undef DECLARE_REGISTER
+const Register no_reg = {Register::kCode_no_reg};
+
 
 #ifdef _WIN64
   // Windows calling convention
-  const Register arg_reg_1 = { kRegister_rcx_Code };
-  const Register arg_reg_2 = { kRegister_rdx_Code };
-  const Register arg_reg_3 = { kRegister_r8_Code };
-  const Register arg_reg_4 = { kRegister_r9_Code };
+const Register arg_reg_1 = {Register::kCode_rcx};
+const Register arg_reg_2 = {Register::kCode_rdx};
+const Register arg_reg_3 = {Register::kCode_r8};
+const Register arg_reg_4 = {Register::kCode_r9};
 #else
   // AMD64 calling convention
-  const Register arg_reg_1 = { kRegister_rdi_Code };
-  const Register arg_reg_2 = { kRegister_rsi_Code };
-  const Register arg_reg_3 = { kRegister_rdx_Code };
-  const Register arg_reg_4 = { kRegister_rcx_Code };
+const Register arg_reg_1 = {Register::kCode_rdi};
+const Register arg_reg_2 = {Register::kCode_rsi};
+const Register arg_reg_3 = {Register::kCode_rdx};
+const Register arg_reg_4 = {Register::kCode_rcx};
 #endif  // _WIN64
 
-struct XMMRegister {
-  static const int kMaxNumRegisters = 16;
-  static const int kMaxNumAllocatableRegisters = 15;
-  static int NumAllocatableRegisters() {
-    return kMaxNumAllocatableRegisters;
-  }
-
-  // TODO(turbofan): Proper support for float32.
-  static int NumAllocatableAliasedRegisters() {
-    return NumAllocatableRegisters();
-  }
-
-  static int ToAllocationIndex(XMMRegister reg) {
-    DCHECK(reg.code() != 0);
-    return reg.code() - 1;
-  }
 
-  static XMMRegister FromAllocationIndex(int index) {
-    DCHECK(0 <= index && index < kMaxNumAllocatableRegisters);
-    XMMRegister result = { index + 1 };
+#define DOUBLE_REGISTERS(V) \
+  V(xmm0)                   \
+  V(xmm1)                   \
+  V(xmm2)                   \
+  V(xmm3)                   \
+  V(xmm4)                   \
+  V(xmm5)                   \
+  V(xmm6)                   \
+  V(xmm7)                   \
+  V(xmm8)                   \
+  V(xmm9)                   \
+  V(xmm10)                  \
+  V(xmm11)                  \
+  V(xmm12)                  \
+  V(xmm13)                  \
+  V(xmm14)                  \
+  V(xmm15)
+
+#define ALLOCATABLE_DOUBLE_REGISTERS(V) \
+  V(xmm1)                               \
+  V(xmm2)                               \
+  V(xmm3)                               \
+  V(xmm4)                               \
+  V(xmm5)                               \
+  V(xmm6)                               \
+  V(xmm7)                               \
+  V(xmm8)                               \
+  V(xmm9)                               \
+  V(xmm10)                              \
+  V(xmm11)                              \
+  V(xmm12)                              \
+  V(xmm13)                              \
+  V(xmm14)                              \
+  V(xmm15)
+
+
+struct DoubleRegister {
+  enum Code {
+#define REGISTER_CODE(R) kCode_##R,
+    DOUBLE_REGISTERS(REGISTER_CODE)
+#undef REGISTER_CODE
+        kAfterLast,
+    kCode_no_reg = -1
+  };
+
+  static const int kMaxNumRegisters = Code::kAfterLast;
+
+  static DoubleRegister from_code(int code) {
+    DoubleRegister result = {code};
     return result;
   }
 
-  static const char* AllocationIndexToString(int index) {
-    DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
-    const char* const names[] = {
-      "xmm1",
-      "xmm2",
-      "xmm3",
-      "xmm4",
-      "xmm5",
-      "xmm6",
-      "xmm7",
-      "xmm8",
-      "xmm9",
-      "xmm10",
-      "xmm11",
-      "xmm12",
-      "xmm13",
-      "xmm14",
-      "xmm15"
-    };
-    return names[index];
-  }
-
-  static XMMRegister from_code(int code) {
-    DCHECK(code >= 0);
-    DCHECK(code < kMaxNumRegisters);
-    XMMRegister r = { code };
-    return r;
-  }
-  bool is_valid() const { return 0 <= code_ && code_ < kMaxNumRegisters; }
-  bool is(XMMRegister reg) const { return code_ == reg.code_; }
+  const char* ToString();
+  bool IsAllocatable() const;
+  bool is_valid() const { return 0 <= reg_code && reg_code < kMaxNumRegisters; }
+  bool is(DoubleRegister reg) const { return reg_code == reg.reg_code; }
   int code() const {
     DCHECK(is_valid());
-    return code_;
+    return reg_code;
   }
 
   // Return the high bit of the register code as a 0 or 1.  Used often
   // when constructing the REX prefix byte.
-  int high_bit() const {
-    return code_ >> 3;
-  }
+  int high_bit() const { return reg_code >> 3; }
   // Return the 3 low bits of the register code.  Used when encoding registers
   // in modR/M, SIB, and opcode bytes.
-  int low_bits() const {
-    return code_ & 0x7;
-  }
+  int low_bits() const { return reg_code & 0x7; }
 
-  int code_;
+  // Unfortunately we can't make this private in a struct when initializing
+  // by assignment.
+  int reg_code;
 };
 
-const XMMRegister xmm0 = { 0 };
-const XMMRegister xmm1 = { 1 };
-const XMMRegister xmm2 = { 2 };
-const XMMRegister xmm3 = { 3 };
-const XMMRegister xmm4 = { 4 };
-const XMMRegister xmm5 = { 5 };
-const XMMRegister xmm6 = { 6 };
-const XMMRegister xmm7 = { 7 };
-const XMMRegister xmm8 = { 8 };
-const XMMRegister xmm9 = { 9 };
-const XMMRegister xmm10 = { 10 };
-const XMMRegister xmm11 = { 11 };
-const XMMRegister xmm12 = { 12 };
-const XMMRegister xmm13 = { 13 };
-const XMMRegister xmm14 = { 14 };
-const XMMRegister xmm15 = { 15 };
-
-
-typedef XMMRegister DoubleRegister;
 
+#define DECLARE_REGISTER(R) \
+  const DoubleRegister R = {DoubleRegister::kCode_##R};
+DOUBLE_REGISTERS(DECLARE_REGISTER)
+#undef DECLARE_REGISTER
+const DoubleRegister no_double_reg = {DoubleRegister::kCode_no_reg};
+
+
+typedef DoubleRegister XMMRegister;
 
 enum Condition {
   // any value < 0 is considered no_condition
index 1344400d48eff7f70642b8cb621d00dfa3f7cf75..d3f92c530c19a2d00e12db33142180d69fe59004 100644 (file)
@@ -294,13 +294,15 @@ class RecordWriteStub: public PlatformCodeStub {
     Register GetRegThatIsNotRcxOr(Register r1,
                                   Register r2,
                                   Register r3) {
-      for (int i = 0; i < Register::NumAllocatableRegisters(); i++) {
-        Register candidate = Register::FromAllocationIndex(i);
-        if (candidate.is(rcx)) continue;
-        if (candidate.is(r1)) continue;
-        if (candidate.is(r2)) continue;
-        if (candidate.is(r3)) continue;
-        return candidate;
+      for (int i = 0; i < Register::kNumRegisters; i++) {
+        Register candidate = Register::from_code(i);
+        if (candidate.IsAllocatable()) {
+          if (candidate.is(rcx)) continue;
+          if (candidate.is(r1)) continue;
+          if (candidate.is(r2)) continue;
+          if (candidate.is(r3)) continue;
+          return candidate;
+        }
       }
       UNREACHABLE();
       return no_reg;
index 72c92f0a39bbfae08505f9314aabb69f1875698b..8ec123a5da9f4ee8cea0e9dec88fbcd172cac3b4 100644 (file)
@@ -7,6 +7,7 @@
 #include "src/codegen.h"
 #include "src/deoptimizer.h"
 #include "src/full-codegen/full-codegen.h"
+#include "src/register-configuration.h"
 #include "src/safepoint-table.h"
 
 namespace v8 {
@@ -95,7 +96,7 @@ void Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) {
   }
   input_->SetRegister(rsp.code(), reinterpret_cast<intptr_t>(frame->sp()));
   input_->SetRegister(rbp.code(), reinterpret_cast<intptr_t>(frame->fp()));
-  for (int i = 0; i < DoubleRegister::NumAllocatableRegisters(); i++) {
+  for (int i = 0; i < DoubleRegister::kMaxNumRegisters; i++) {
     input_->SetDoubleRegister(i, 0.0);
   }
 
@@ -117,7 +118,7 @@ void Deoptimizer::SetPlatformCompiledStubRegisters(
 
 
 void Deoptimizer::CopyDoubleRegisters(FrameDescription* output_frame) {
-  for (int i = 0; i < XMMRegister::NumAllocatableRegisters(); ++i) {
+  for (int i = 0; i < XMMRegister::kMaxNumRegisters; ++i) {
     double double_value = input_->GetDoubleRegister(i);
     output_frame->SetDoubleRegister(i, double_value);
   }
@@ -138,13 +139,14 @@ void Deoptimizer::TableEntryGenerator::Generate() {
   // Save all general purpose registers before messing with them.
   const int kNumberOfRegisters = Register::kNumRegisters;
 
-  const int kDoubleRegsSize = kDoubleSize *
-      XMMRegister::NumAllocatableRegisters();
+  const int kDoubleRegsSize = kDoubleSize * XMMRegister::kMaxNumRegisters;
   __ subp(rsp, Immediate(kDoubleRegsSize));
 
-  for (int i = 0; i < XMMRegister::NumAllocatableRegisters(); ++i) {
-    XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i);
-    int offset = i * kDoubleSize;
+  const RegisterConfiguration* config = RegisterConfiguration::ArchDefault();
+  for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
+    int code = config->GetAllocatableDoubleCode(i);
+    XMMRegister xmm_reg = XMMRegister::from_code(code);
+    int offset = code * kDoubleSize;
     __ movsd(Operand(rsp, offset), xmm_reg);
   }
 
@@ -210,7 +212,7 @@ void Deoptimizer::TableEntryGenerator::Generate() {
 
   // Fill in the double input registers.
   int double_regs_offset = FrameDescription::double_registers_offset();
-  for (int i = 0; i < XMMRegister::NumAllocatableRegisters(); i++) {
+  for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) {
     int dst_offset = i * kDoubleSize + double_regs_offset;
     __ popq(Operand(rbx, dst_offset));
   }
@@ -274,9 +276,10 @@ void Deoptimizer::TableEntryGenerator::Generate() {
   __ cmpp(rax, rdx);
   __ j(below, &outer_push_loop);
 
-  for (int i = 0; i < XMMRegister::NumAllocatableRegisters(); ++i) {
-    XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i);
-    int src_offset = i * kDoubleSize + double_regs_offset;
+  for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
+    int code = config->GetAllocatableDoubleCode(i);
+    XMMRegister xmm_reg = XMMRegister::from_code(code);
+    int src_offset = code * kDoubleSize + double_regs_offset;
     __ movsd(xmm_reg, Operand(rbx, src_offset));
   }
 
index 81d275f7a9d60bb7dc6cc5ab3291c332cd3d33b4..1a2fd8a9e8b1c48a912d778f052ce77eec4a6e3b 100644 (file)
@@ -89,7 +89,7 @@ void LCodeGen::SaveCallerDoubles() {
   BitVector::Iterator save_iterator(doubles);
   while (!save_iterator.Done()) {
     __ movsd(MemOperand(rsp, count * kDoubleSize),
-             XMMRegister::FromAllocationIndex(save_iterator.Current()));
+             XMMRegister::from_code(save_iterator.Current()));
     save_iterator.Advance();
     count++;
   }
@@ -104,7 +104,7 @@ void LCodeGen::RestoreCallerDoubles() {
   BitVector::Iterator save_iterator(doubles);
   int count = 0;
   while (!save_iterator.Done()) {
-    __ movsd(XMMRegister::FromAllocationIndex(save_iterator.Current()),
+    __ movsd(XMMRegister::from_code(save_iterator.Current()),
              MemOperand(rsp, count * kDoubleSize));
     save_iterator.Advance();
     count++;
@@ -437,12 +437,12 @@ bool LCodeGen::GenerateSafepointTable() {
 
 
 Register LCodeGen::ToRegister(int index) const {
-  return Register::FromAllocationIndex(index);
+  return Register::from_code(index);
 }
 
 
 XMMRegister LCodeGen::ToDoubleRegister(int index) const {
-  return XMMRegister::FromAllocationIndex(index);
+  return XMMRegister::from_code(index);
 }
 
 
index 9df3a7dabf328745bf4731be4f0dd46ed97d8772..722ab01be2b5396b98de40a7967c346cce5dd83a 100644 (file)
@@ -470,14 +470,13 @@ LPlatformChunk* LChunkBuilder::Build() {
 
 
 LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
-  return new(zone()) LUnallocated(LUnallocated::FIXED_REGISTER,
-                                  Register::ToAllocationIndex(reg));
+  return new (zone()) LUnallocated(LUnallocated::FIXED_REGISTER, reg.code());
 }
 
 
 LUnallocated* LChunkBuilder::ToUnallocated(XMMRegister reg) {
-  return new(zone()) LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER,
-                                  XMMRegister::ToAllocationIndex(reg));
+  return new (zone())
+      LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER, reg.code());
 }
 
 
index 0361828eb5f901823404ca4ad571cfcc189b5f30..3eb3b2ff0b4a4c301c7050ec4eb01433ae005e4f 100644 (file)
@@ -11,6 +11,7 @@
 #include "src/cpu-profiler.h"
 #include "src/debug/debug.h"
 #include "src/heap/heap.h"
+#include "src/register-configuration.h"
 #include "src/x64/assembler-x64.h"
 #include "src/x64/macro-assembler-x64.h"
 
@@ -730,7 +731,8 @@ void MacroAssembler::GetBuiltinEntry(Register target,
 }
 
 
-#define REG(Name) { kRegister_ ## Name ## _Code }
+#define REG(Name) \
+  { Register::kCode_##Name }
 
 static const Register saved_regs[] = {
   REG(rax), REG(rcx), REG(rdx), REG(rbx), REG(rbp), REG(rsi), REG(rdi), REG(r8),
@@ -3704,12 +3706,14 @@ void MacroAssembler::EnterExitFrameEpilogue(int arg_stack_space,
 #endif
   // Optionally save all XMM registers.
   if (save_doubles) {
-    int space = XMMRegister::kMaxNumAllocatableRegisters * kDoubleSize +
-        arg_stack_space * kRegisterSize;
+    int space = XMMRegister::kMaxNumRegisters * kDoubleSize +
+                arg_stack_space * kRegisterSize;
     subp(rsp, Immediate(space));
     int offset = -2 * kPointerSize;
-    for (int i = 0; i < XMMRegister::NumAllocatableRegisters(); i++) {
-      XMMRegister reg = XMMRegister::FromAllocationIndex(i);
+    const RegisterConfiguration* config = RegisterConfiguration::ArchDefault();
+    for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
+      DoubleRegister reg =
+          DoubleRegister::from_code(config->GetAllocatableDoubleCode(i));
       movsd(Operand(rbp, offset - ((i + 1) * kDoubleSize)), reg);
     }
   } else if (arg_stack_space > 0) {
@@ -3752,8 +3756,10 @@ void MacroAssembler::LeaveExitFrame(bool save_doubles) {
   // r15 : argv
   if (save_doubles) {
     int offset = -2 * kPointerSize;
-    for (int i = 0; i < XMMRegister::NumAllocatableRegisters(); i++) {
-      XMMRegister reg = XMMRegister::FromAllocationIndex(i);
+    const RegisterConfiguration* config = RegisterConfiguration::ArchDefault();
+    for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
+      DoubleRegister reg =
+          DoubleRegister::from_code(config->GetAllocatableDoubleCode(i));
       movsd(reg, Operand(rbp, offset - ((i + 1) * kDoubleSize)));
     }
   }
index 7d392a294bfa6b1fa949caa3fce0664c76b54fa8..27137af9f74f9ef204f1ec48acdfe65959de916a 100644 (file)
@@ -16,17 +16,17 @@ namespace v8 {
 namespace internal {
 
 // Give alias names to registers for calling conventions.
-const Register kReturnRegister0 = {kRegister_rax_Code};
-const Register kReturnRegister1 = {kRegister_rdx_Code};
-const Register kJSFunctionRegister = {kRegister_rdi_Code};
-const Register kContextRegister = {kRegister_rsi_Code};
-const Register kInterpreterAccumulatorRegister = {kRegister_rax_Code};
-const Register kInterpreterRegisterFileRegister = {kRegister_r11_Code};
-const Register kInterpreterBytecodeOffsetRegister = {kRegister_r12_Code};
-const Register kInterpreterBytecodeArrayRegister = {kRegister_r14_Code};
-const Register kInterpreterDispatchTableRegister = {kRegister_r15_Code};
-const Register kRuntimeCallFunctionRegister = {kRegister_rbx_Code};
-const Register kRuntimeCallArgCountRegister = {kRegister_rax_Code};
+const Register kReturnRegister0 = {Register::kCode_rax};
+const Register kReturnRegister1 = {Register::kCode_rdx};
+const Register kJSFunctionRegister = {Register::kCode_rdi};
+const Register kContextRegister = {Register::kCode_rsi};
+const Register kInterpreterAccumulatorRegister = {Register::kCode_rax};
+const Register kInterpreterRegisterFileRegister = {Register::kCode_r11};
+const Register kInterpreterBytecodeOffsetRegister = {Register::kCode_r12};
+const Register kInterpreterBytecodeArrayRegister = {Register::kCode_r14};
+const Register kInterpreterDispatchTableRegister = {Register::kCode_r15};
+const Register kRuntimeCallFunctionRegister = {Register::kCode_rbx};
+const Register kRuntimeCallArgCountRegister = {Register::kCode_rax};
 
 // Default scratch register used by MacroAssembler (and other code that needs
 // a spare register). The register isn't callee save, and not used by the
index 1f454bcd9023275bc8a8e0e7ccaeaf10a119b33b..a2a90dfc3ccd764b8c8b5a6a17c04fa897825d3e 100644 (file)
@@ -76,10 +76,6 @@ struct Register {
 
   static inline const char* AllocationIndexToString(int index);
 
-  static inline int ToAllocationIndex(Register reg);
-
-  static inline Register FromAllocationIndex(int index);
-
   static Register from_code(int code) {
     DCHECK(code >= 0);
     DCHECK(code < kNumRegisters);
@@ -132,18 +128,6 @@ inline const char* Register::AllocationIndexToString(int index) {
 }
 
 
-inline int Register::ToAllocationIndex(Register reg) {
-  DCHECK(reg.is_valid() && !reg.is(esp) && !reg.is(ebp));
-  return (reg.code() >= 6) ? reg.code() - 2 : reg.code();
-}
-
-
-inline Register Register::FromAllocationIndex(int index)  {
-  DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
-  return (index >= 4) ? from_code(index + 2) : from_code(index);
-}
-
-
 struct X87Register {
   static const int kMaxNumAllocatableRegisters = 6;
   static const int kMaxNumRegisters = 8;
index a081ddb8fe9d79410692e8fb43413b693e1ec2a0..7dade3df33a5d821a71f6a2acab2d57e37149f1b 100644 (file)
@@ -73,7 +73,13 @@ class InterpreterState {
     AllocatedOperand::AllocatedKind kind;
     int index;
     if (!is_constant) {
-      index = AllocatedOperand::cast(op).index();
+      if (op.IsRegister()) {
+        index = AllocatedOperand::cast(op).GetRegister().code();
+      } else if (op.IsDoubleRegister()) {
+        index = AllocatedOperand::cast(op).GetDoubleRegister().code();
+      } else {
+        index = AllocatedOperand::cast(op).index();
+      }
       kind = AllocatedOperand::cast(op).allocated_kind();
     } else {
       index = ConstantOperand::cast(op).virtual_register();
@@ -90,7 +96,9 @@ class InterpreterState {
       return ConstantOperand(key.index);
     }
     return AllocatedOperand(
-        key.kind, InstructionSequence::DefaultRepresentation(), key.index);
+        key.kind,
+        v8::internal::compiler::InstructionSequence::DefaultRepresentation(),
+        key.index);
   }
 
   friend std::ostream& operator<<(std::ostream& os,
index bc6acf1bc97b4d57cc777ce9846cc03e898f8e30..af3748b8fd1b8049445a3155b8ecda39b779b1fa 100644 (file)
@@ -7,6 +7,7 @@
 #include "src/compiler/linkage.h"
 #include "src/compiler/machine-type.h"
 #include "src/compiler/raw-machine-assembler.h"
+#include "src/register-configuration.h"
 
 #include "test/cctest/cctest.h"
 #include "test/cctest/compiler/codegen-tester.h"
@@ -35,8 +36,9 @@ typedef double float64;
 // to select a representative set.
 class Pairs {
  public:
-  Pairs(int max_pairs, int range)
+  Pairs(int max_pairs, int range, const int* codes)
       : range_(range),
+        codes_(codes),
         max_pairs_(std::min(max_pairs, range_ * range_)),
         counter_(0) {}
 
@@ -46,37 +48,33 @@ class Pairs {
     do {
       // Find the next pair.
       if (exhaustive()) {
-        *r0 = counter_ % range_;
-        *r1 = counter_ / range_;
+        *r0 = codes_[counter_ % range_];
+        *r1 = codes_[counter_ / range_];
       } else {
         // Try each integer at least once for both r0 and r1.
         int index = counter_ / 2;
         if (counter_ & 1) {
-          *r0 = index % range_;
-          *r1 = index / range_;
+          *r0 = codes_[index % range_];
+          *r1 = codes_[index / range_];
         } else {
-          *r1 = index % range_;
-          *r0 = index / range_;
+          *r1 = codes_[index % range_];
+          *r0 = codes_[index / range_];
         }
       }
       counter_++;
-      if (same_is_ok) break;
-      if (*r0 == *r1) {
-        if (counter_ >= max_pairs_) {
-          // For the last hurrah, reg#0 with reg#n-1
-          *r0 = 0;
-          *r1 = range_ - 1;
-          break;
-        }
+      if ((same_is_ok) || (*r0 != *r1)) break;
+      if (counter_ == max_pairs_) {
+        // For the last hurrah, reg#0 with reg#n-1
+        *r0 = codes_[0];
+        *r1 = codes_[range_ - 1];
+        break;
       }
     } while (true);
-
-    DCHECK(*r0 >= 0 && *r0 < range_);
-    DCHECK(*r1 >= 0 && *r1 < range_);
   }
 
  private:
   int range_;
+  const int* codes_;
   int max_pairs_;
   int counter_;
   bool exhaustive() { return max_pairs_ == (range_ * range_); }
@@ -86,7 +84,12 @@ class Pairs {
 // Pairs of general purpose registers.
 class RegisterPairs : public Pairs {
  public:
-  RegisterPairs() : Pairs(100, Register::kMaxNumAllocatableRegisters) {}
+  RegisterPairs()
+      : Pairs(
+            100, RegisterConfiguration::ArchDefault()
+                     ->num_allocatable_general_registers(),
+            RegisterConfiguration::ArchDefault()->allocatable_general_codes()) {
+  }
 };
 
 
@@ -94,7 +97,10 @@ class RegisterPairs : public Pairs {
 class Float32RegisterPairs : public Pairs {
  public:
   Float32RegisterPairs()
-      : Pairs(100, DoubleRegister::NumAllocatableAliasedRegisters()) {}
+      : Pairs(
+            100, RegisterConfiguration::ArchDefault()
+                     ->num_allocatable_aliased_double_registers(),
+            RegisterConfiguration::ArchDefault()->allocatable_double_codes()) {}
 };
 
 
@@ -102,7 +108,10 @@ class Float32RegisterPairs : public Pairs {
 class Float64RegisterPairs : public Pairs {
  public:
   Float64RegisterPairs()
-      : Pairs(100, DoubleRegister::NumAllocatableAliasedRegisters()) {}
+      : Pairs(
+            100, RegisterConfiguration::ArchDefault()
+                     ->num_allocatable_aliased_double_registers(),
+            RegisterConfiguration::ArchDefault()->allocatable_double_codes()) {}
 };
 
 
@@ -624,9 +633,12 @@ static void Test_RunInt32SubWithRet(int retreg) {
 
 
 // Separate tests for parallelization.
-#define TEST_INT32_SUB_WITH_RET(x)                                             \
-  TEST(Run_Int32Sub_all_allocatable_pairs_##x) {                               \
-    if (Register::kMaxNumAllocatableRegisters > x) Test_RunInt32SubWithRet(x); \
+#define TEST_INT32_SUB_WITH_RET(x)                \
+  TEST(Run_Int32Sub_all_allocatable_pairs_##x) {  \
+    if (x < Register::kNumRegisters &&            \
+        Register::from_code(x).IsAllocatable()) { \
+      Test_RunInt32SubWithRet(x);                 \
+    }                                             \
   }
 
 
@@ -677,7 +689,8 @@ TEST(Run_CopyTwentyInt32_all_allocatable_pairs) {
   while (pairs.More()) {
     Zone zone;
     int parray[2];
-    int rarray[] = {0};
+    int rarray[] = {
+        RegisterConfiguration::ArchDefault()->GetAllocatableGeneralCode(0)};
     pairs.Next(&parray[0], &parray[1], false);
     Allocator params(parray, 2, nullptr, 0);
     Allocator rets(rarray, 1, nullptr, 0);
@@ -724,17 +737,20 @@ static int32_t Compute_Int32_WeightedSum(CallDescriptor* desc, int32_t* input) {
 static void Test_Int32_WeightedSum_of_size(int count) {
   if (DISABLE_NATIVE_STACK_PARAMS) return;
   Int32Signature sig(count);
-  for (int p0 = 0; p0 < Register::kMaxNumAllocatableRegisters; p0++) {
-    Zone zone;
+  for (int p0 = 0; p0 < Register::kNumRegisters; p0++) {
+    if (Register::from_code(p0).IsAllocatable()) {
+      Zone zone;
 
-    int parray[] = {p0};
-    int rarray[] = {0};
-    Allocator params(parray, 1, nullptr, 0);
-    Allocator rets(rarray, 1, nullptr, 0);
-    RegisterConfig config(params, rets);
-    CallDescriptor* desc = config.Create(&zone, &sig);
-    Run_Computation<int32_t>(desc, Build_Int32_WeightedSum,
-                             Compute_Int32_WeightedSum, 257 + count);
+      int parray[] = {p0};
+      int rarray[] = {
+          RegisterConfiguration::ArchDefault()->GetAllocatableGeneralCode(0)};
+      Allocator params(parray, 1, nullptr, 0);
+      Allocator rets(rarray, 1, nullptr, 0);
+      RegisterConfig config(params, rets);
+      CallDescriptor* desc = config.Create(&zone, &sig);
+      Run_Computation<int32_t>(desc, Build_Int32_WeightedSum,
+                               Compute_Int32_WeightedSum, 257 + count);
+    }
   }
 }
 
@@ -782,8 +798,10 @@ template <int which>
 void Test_Int32_Select() {
   if (DISABLE_NATIVE_STACK_PARAMS) return;
 
-  int parray[] = {0};
-  int rarray[] = {0};
+  int parray[] = {
+      RegisterConfiguration::ArchDefault()->GetAllocatableGeneralCode(0)};
+  int rarray[] = {
+      RegisterConfiguration::ArchDefault()->GetAllocatableGeneralCode(0)};
   Allocator params(parray, 1, nullptr, 0);
   Allocator rets(rarray, 1, nullptr, 0);
   RegisterConfig config(params, rets);
@@ -819,10 +837,13 @@ TEST_INT32_SELECT(63)
 
 
 TEST(Int64Select_registers) {
-  if (Register::kMaxNumAllocatableRegisters < 2) return;
+  if (RegisterConfiguration::ArchDefault()
+          ->num_allocatable_general_registers() < 2)
+    return;
   if (kPointerSize < 8) return;  // TODO(titzer): int64 on 32-bit platforms
 
-  int rarray[] = {0};
+  int rarray[] = {
+      RegisterConfiguration::ArchDefault()->GetAllocatableGeneralCode(0)};
   ArgsBuffer<int64_t>::Sig sig(2);
 
   RegisterPairs pairs;
@@ -842,9 +863,13 @@ TEST(Int64Select_registers) {
 
 
 TEST(Float32Select_registers) {
-  if (RegisterConfiguration::ArchDefault()->num_double_registers() < 2) return;
+  if (RegisterConfiguration::ArchDefault()->num_allocatable_double_registers() <
+      2) {
+    return;
+  }
 
-  int rarray[] = {0};
+  int rarray[] = {
+      RegisterConfiguration::ArchDefault()->GetAllocatableDoubleCode(0)};
   ArgsBuffer<float32>::Sig sig(2);
 
   Float32RegisterPairs pairs;
@@ -864,9 +889,14 @@ TEST(Float32Select_registers) {
 
 
 TEST(Float64Select_registers) {
-  if (RegisterConfiguration::ArchDefault()->num_double_registers() < 2) return;
-
-  int rarray[] = {0};
+  if (RegisterConfiguration::ArchDefault()->num_allocatable_double_registers() <
+      2)
+    return;
+  if (RegisterConfiguration::ArchDefault()
+          ->num_allocatable_general_registers() < 2)
+    return;
+  int rarray[] = {
+      RegisterConfiguration::ArchDefault()->GetAllocatableDoubleCode(0)};
   ArgsBuffer<float64>::Sig sig(2);
 
   Float64RegisterPairs pairs;
@@ -887,7 +917,8 @@ TEST(Float64Select_registers) {
 
 TEST(Float32Select_stack_params_return_reg) {
   if (DISABLE_NATIVE_STACK_PARAMS) return;
-  int rarray[] = {0};
+  int rarray[] = {
+      RegisterConfiguration::ArchDefault()->GetAllocatableDoubleCode(0)};
   Allocator params(nullptr, 0, nullptr, 0);
   Allocator rets(nullptr, 0, rarray, 1);
   RegisterConfig config(params, rets);
@@ -908,7 +939,8 @@ TEST(Float32Select_stack_params_return_reg) {
 
 TEST(Float64Select_stack_params_return_reg) {
   if (DISABLE_NATIVE_STACK_PARAMS) return;
-  int rarray[] = {0};
+  int rarray[] = {
+      RegisterConfiguration::ArchDefault()->GetAllocatableDoubleCode(0)};
   Allocator params(nullptr, 0, nullptr, 0);
   Allocator rets(nullptr, 0, rarray, 1);
   RegisterConfig config(params, rets);
@@ -962,7 +994,8 @@ static void Build_Select_With_Call(CallDescriptor* desc,
 TEST(Float64StackParamsToStackParams) {
   if (DISABLE_NATIVE_STACK_PARAMS) return;
 
-  int rarray[] = {0};
+  int rarray[] = {
+      RegisterConfiguration::ArchDefault()->GetAllocatableDoubleCode(0)};
   Allocator params(nullptr, 0, nullptr, 0);
   Allocator rets(nullptr, 0, rarray, 1);
 
@@ -1005,10 +1038,18 @@ void MixedParamTest(int start) {
   const int num_params = static_cast<int>(arraysize(types) - start);
 
   // Build call descriptor
-  int parray[] = {0, 1};
-  int rarray[] = {0};
-  Allocator palloc(parray, 2, parray, 2);
-  Allocator ralloc(rarray, 1, rarray, 1);
+  int parray_gp[] = {
+      RegisterConfiguration::ArchDefault()->GetAllocatableGeneralCode(0),
+      RegisterConfiguration::ArchDefault()->GetAllocatableGeneralCode(1)};
+  int rarray_gp[] = {
+      RegisterConfiguration::ArchDefault()->GetAllocatableGeneralCode(0)};
+  int parray_fp[] = {
+      RegisterConfiguration::ArchDefault()->GetAllocatableDoubleCode(0),
+      RegisterConfiguration::ArchDefault()->GetAllocatableDoubleCode(1)};
+  int rarray_fp[] = {
+      RegisterConfiguration::ArchDefault()->GetAllocatableDoubleCode(0)};
+  Allocator palloc(parray_gp, 2, parray_fp, 2);
+  Allocator ralloc(rarray_gp, 1, rarray_fp, 1);
   RegisterConfig config(palloc, ralloc);
 
   for (int which = 0; which < num_params; which++) {
index 33145444c7230fd1c58c087ad83e70b7e80e6585..385718f486c9cd037c03b2cb4fd56d35029e0373 100644 (file)
@@ -76,11 +76,13 @@ ConvertDToIFunc MakeConvertDToIFuncTrampoline(Isolate* isolate,
   // Save registers make sure they don't get clobbered.
   int source_reg_offset = kDoubleSize;
   int reg_num = 0;
-  for (;reg_num < Register::NumAllocatableRegisters(); ++reg_num) {
+  for (; reg_num < Register::kNumRegisters; ++reg_num) {
     Register reg = Register::from_code(reg_num);
-    if (!reg.is(destination_reg)) {
-      __ push(reg);
-      source_reg_offset += kPointerSize;
+    if (reg.IsAllocatable()) {
+      if (!reg.is(destination_reg)) {
+        __ push(reg);
+        source_reg_offset += kPointerSize;
+      }
     }
   }
 
@@ -105,11 +107,13 @@ ConvertDToIFunc MakeConvertDToIFuncTrampoline(Isolate* isolate,
   // Make sure no registers have been unexpectedly clobbered
   for (--reg_num; reg_num >= 0; --reg_num) {
     Register reg = Register::from_code(reg_num);
-    if (!reg.is(destination_reg)) {
-      __ ldr(ip, MemOperand(sp, 0));
-      __ cmp(reg, ip);
-      __ Assert(eq, kRegisterWasClobbered);
-      __ add(sp, sp, Operand(kPointerSize));
+    if (reg.IsAllocatable()) {
+      if (!reg.is(destination_reg)) {
+        __ ldr(ip, MemOperand(sp, 0));
+        __ cmp(reg, ip);
+        __ Assert(eq, kRegisterWasClobbered);
+        __ add(sp, sp, Operand(kPointerSize));
+      }
     }
   }
 
index ecb8819345378667c3ae774954c4185c07e600e4..c7a6cdb4be0e5f94a01c710fa884d2bee9666f4b 100644 (file)
@@ -72,11 +72,13 @@ ConvertDToIFunc MakeConvertDToIFuncTrampoline(Isolate* isolate,
   // Save registers make sure they don't get clobbered.
   int source_reg_offset = kDoubleSize;
   int reg_num = 0;
-  for (;reg_num < Register::NumAllocatableRegisters(); ++reg_num) {
+  for (; reg_num < Register::kNumRegisters; ++reg_num) {
     Register reg = Register::from_code(reg_num);
-    if (!reg.is(destination_reg)) {
-      queue.Queue(reg);
-      source_reg_offset += kPointerSize;
+    if (reg.IsAllocatable()) {
+      if (!reg.is(destination_reg)) {
+        queue.Queue(reg);
+        source_reg_offset += kPointerSize;
+      }
     }
   }
   // Re-push the double argument.
@@ -101,10 +103,12 @@ ConvertDToIFunc MakeConvertDToIFuncTrampoline(Isolate* isolate,
   // // Make sure no registers have been unexpectedly clobbered
   for (--reg_num; reg_num >= 0; --reg_num) {
     Register reg = Register::from_code(reg_num);
-    if (!reg.is(destination_reg)) {
-      __ Pop(ip0);
-      __ cmp(reg, ip0);
-      __ Assert(eq, kRegisterWasClobbered);
+    if (reg.IsAllocatable()) {
+      if (!reg.is(destination_reg)) {
+        __ Pop(ip0);
+        __ cmp(reg, ip0);
+        __ Assert(eq, kRegisterWasClobbered);
+      }
     }
   }
 
index 0b4a8d417bccd1e998c20a8c49669bf6cf6e8ba5..e0f9a453ed20fc65c8fea39f37aa47fc145efe8a 100644 (file)
@@ -70,11 +70,13 @@ ConvertDToIFunc MakeConvertDToIFuncTrampoline(Isolate* isolate,
   int param_offset = 7 * kPointerSize;
   // Save registers make sure they don't get clobbered.
   int reg_num = 0;
-  for (;reg_num < Register::NumAllocatableRegisters(); ++reg_num) {
-    Register reg = Register::FromAllocationIndex(reg_num);
-    if (!reg.is(esp) && !reg.is(ebp) && !reg.is(destination_reg)) {
-      __ push(reg);
-      param_offset += kPointerSize;
+  for (; reg_num < Register::kNumRegisters; ++reg_num) {
+    Register reg = Register::from_code(reg_num);
+    if (reg.IsAllocatable()) {
+      if (!reg.is(esp) && !reg.is(ebp) && !reg.is(destination_reg)) {
+        __ push(reg);
+        param_offset += kPointerSize;
+      }
     }
   }
 
@@ -89,11 +91,13 @@ ConvertDToIFunc MakeConvertDToIFuncTrampoline(Isolate* isolate,
 
   // Make sure no registers have been unexpectedly clobbered
   for (--reg_num; reg_num >= 0; --reg_num) {
-    Register reg = Register::FromAllocationIndex(reg_num);
-    if (!reg.is(esp) && !reg.is(ebp) && !reg.is(destination_reg)) {
-      __ cmp(reg, MemOperand(esp, 0));
-      __ Assert(equal, kRegisterWasClobbered);
-      __ add(esp, Immediate(kPointerSize));
+    Register reg = Register::from_code(reg_num);
+    if (reg.IsAllocatable()) {
+      if (!reg.is(esp) && !reg.is(ebp) && !reg.is(destination_reg)) {
+        __ cmp(reg, MemOperand(esp, 0));
+        __ Assert(equal, kRegisterWasClobbered);
+        __ add(esp, Immediate(kPointerSize));
+      }
     }
   }
 
index eb3ba02ce878a910ed2dd7275b1e772d0efd64ff..e64eedf84233ae27cd66c8ef141bfd74a3f16afb 100644 (file)
@@ -34,6 +34,7 @@
 #include "src/factory.h"
 #include "src/macro-assembler.h"
 #include "src/mips/constants-mips.h"
+#include "src/register-configuration.h"
 #include "src/simulator.h"
 #include "test/cctest/cctest.h"
 #include "test/cctest/test-code-stubs.h"
@@ -79,7 +80,8 @@ ConvertDToIFunc MakeConvertDToIFuncTrampoline(Isolate* isolate,
   // Save registers make sure they don't get clobbered.
   int source_reg_offset = kDoubleSize;
   int reg_num = 2;
-  for (;reg_num < Register::NumAllocatableRegisters(); ++reg_num) {
+  const RegisterConfiguration* config = RegisterConfiguration::ArchDefault();
+  for (; reg_num < config->num_allocatable_general_registers(); ++reg_num) {
     Register reg = Register::from_code(reg_num);
     if (!reg.is(destination_reg)) {
       __ push(reg);
index 1415cec0798eacbc662c231fa0f1876ec5f9712c..fde2d07a9c12864b3096b9e9d7d9dec8daa3cbb6 100644 (file)
@@ -34,6 +34,7 @@
 #include "src/factory.h"
 #include "src/macro-assembler.h"
 #include "src/mips64/constants-mips64.h"
+#include "src/register-configuration.h"
 #include "src/simulator.h"
 #include "test/cctest/cctest.h"
 #include "test/cctest/test-code-stubs.h"
@@ -79,7 +80,8 @@ ConvertDToIFunc MakeConvertDToIFuncTrampoline(Isolate* isolate,
   // Save registers make sure they don't get clobbered.
   int source_reg_offset = kDoubleSize;
   int reg_num = 2;
-  for (;reg_num < Register::NumAllocatableRegisters(); ++reg_num) {
+  const RegisterConfiguration* config = RegisterConfiguration::ArchDefault();
+  for (; reg_num < config->num_allocatable_general_registers(); ++reg_num) {
     Register reg = Register::from_code(reg_num);
     if (!reg.is(destination_reg)) {
       __ push(reg);
index b58b073f3b7939736499e39caa4fea653634a53c..8f22dd9fcfc48f595114f7351e7257f1bbddba21 100644 (file)
@@ -33,6 +33,7 @@
 #include "src/code-stubs.h"
 #include "src/factory.h"
 #include "src/macro-assembler.h"
+#include "src/register-configuration.h"
 #include "test/cctest/cctest.h"
 #include "test/cctest/test-code-stubs.h"
 
@@ -62,20 +63,24 @@ ConvertDToIFunc MakeConvertDToIFuncTrampoline(Isolate* isolate,
   __ pushq(rsi);
   __ pushq(rdi);
 
+
+  const RegisterConfiguration* config = RegisterConfiguration::ArchDefault();
   if (!source_reg.is(rsp)) {
     // The argument we pass to the stub is not a heap number, but instead
     // stack-allocated and offset-wise made to look like a heap number for
     // the stub.  We create that "heap number" after pushing all allocatable
     // registers.
     int double_argument_slot =
-        (Register::NumAllocatableRegisters() - 1) * kPointerSize + kDoubleSize;
+        (config->num_allocatable_general_registers() - 1) * kPointerSize +
+        kDoubleSize;
     __ leaq(source_reg, MemOperand(rsp, -double_argument_slot - offset));
   }
 
   // Save registers make sure they don't get clobbered.
   int reg_num = 0;
-  for (;reg_num < Register::NumAllocatableRegisters(); ++reg_num) {
-    Register reg = Register::FromAllocationIndex(reg_num);
+  for (; reg_num < config->num_allocatable_general_registers(); ++reg_num) {
+    Register reg =
+        Register::from_code(config->GetAllocatableGeneralCode(reg_num));
     if (!reg.is(rsp) && !reg.is(rbp) && !reg.is(destination_reg)) {
       __ pushq(reg);
     }
@@ -92,7 +97,8 @@ ConvertDToIFunc MakeConvertDToIFuncTrampoline(Isolate* isolate,
 
   // Make sure no registers have been unexpectedly clobbered
   for (--reg_num; reg_num >= 0; --reg_num) {
-    Register reg = Register::FromAllocationIndex(reg_num);
+    Register reg =
+        Register::from_code(config->GetAllocatableGeneralCode(reg_num));
     if (!reg.is(rsp) && !reg.is(rbp) && !reg.is(destination_reg)) {
       __ cmpq(reg, MemOperand(rsp, 0));
       __ Assert(equal, kRegisterWasClobbered);
index e14382e914a214378c81a5f52a3886ba4ee3f798..76bfe2217183f1b2a270c290f6bf1d73bc910fda 100644 (file)
@@ -127,8 +127,7 @@ bool InstructionSelectorTest::Stream::IsFixed(const InstructionOperand* operand,
   if (!operand->IsUnallocated()) return false;
   const UnallocatedOperand* unallocated = UnallocatedOperand::cast(operand);
   if (!unallocated->HasFixedRegisterPolicy()) return false;
-  const int index = Register::ToAllocationIndex(reg);
-  return unallocated->fixed_register_index() == index;
+  return unallocated->fixed_register_index() == reg.code();
 }
 
 
index 65a7f299c5565703e5f07022facef32546c2f512..51112a6470ee24e9d21ff18936a9d9554f782aa2 100644 (file)
@@ -20,6 +20,14 @@ static char register_names_[10 * (RegisterConfiguration::kMaxGeneralRegisters +
                                   RegisterConfiguration::kMaxDoubleRegisters)];
 
 
+namespace {
+static int allocatable_codes[InstructionSequenceTest::kDefaultNRegs] = {
+    0, 1, 2, 3, 4, 5, 6, 7};
+static int allocatable_double_codes[InstructionSequenceTest::kDefaultNRegs] = {
+    0, 1, 2, 3, 4, 5, 6, 7};
+}
+
+
 static void InitializeRegisterNames() {
   char* loc = register_names_;
   for (int i = 0; i < RegisterConfiguration::kMaxGeneralRegisters; ++i) {
@@ -59,8 +67,10 @@ void InstructionSequenceTest::SetNumRegs(int num_general_registers,
 RegisterConfiguration* InstructionSequenceTest::config() {
   if (config_.is_empty()) {
     config_.Reset(new RegisterConfiguration(
-        num_general_registers_, num_double_registers_, num_double_registers_,
-        general_register_names_, double_register_names_));
+        num_general_registers_, num_double_registers_, num_general_registers_,
+        num_double_registers_, num_double_registers_, allocatable_codes,
+        allocatable_double_codes, general_register_names_,
+        double_register_names_));
   }
   return config_.get();
 }
index 54317ede21c6107ac04977456012a33a3c98fc35..e5e5139f970295eb81b4c0c56e0383a020b153ef 100644 (file)
@@ -15,7 +15,7 @@ namespace compiler {
 
 class InstructionSequenceTest : public TestWithIsolateAndZone {
  public:
-  static const int kDefaultNRegs = 4;
+  static const int kDefaultNRegs = 8;
   static const int kNoValue = kMinInt;
 
   typedef RpoNumber Rpo;
index 23a118b6ad157783b13d7fe85cc3fd7613adabde..0fd41d918d670b8b2f19fda0fbb9ca5497ae38c8 100644 (file)
@@ -41,7 +41,8 @@ bool AllocatedOperandMatches(
     const AllocatedOperand& op,
     const InstructionSequenceTest::TestOperand& test_op) {
   return AreOperandsOfSameType(op, test_op) &&
-         (op.index() == test_op.value_ ||
+         ((op.IsRegister() ? op.GetRegister().code() : op.index()) ==
+              test_op.value_ ||
           test_op.value_ == InstructionSequenceTest::kNoValue);
 }
 
index c8abd433a4a83a03f454c87d3fea1c0cfea5ab3a..3d895c16628fa948d19001186893a0442189e275 100644 (file)
         '../../src/compiler/register-allocator.h',
         '../../src/compiler/register-allocator-verifier.cc',
         '../../src/compiler/register-allocator-verifier.h',
-        '../../src/compiler/register-configuration.cc',
-        '../../src/compiler/register-configuration.h',
         '../../src/compiler/representation-change.h',
         '../../src/compiler/schedule.cc',
         '../../src/compiler/schedule.h',
         '../../src/regexp/regexp-macro-assembler.h',
         '../../src/regexp/regexp-stack.cc',
         '../../src/regexp/regexp-stack.h',
+        '../../src/register-configuration.cc',
+        '../../src/register-configuration.h',
         '../../src/rewriter.cc',
         '../../src/rewriter.h',
         '../../src/runtime-profiler.cc',