From 5cf1c0bcf6f10ff61a95a00fa302eeee7c390885 Mon Sep 17 00:00:00 2001 From: danno Date: Fri, 2 Oct 2015 09:55:12 -0700 Subject: [PATCH] Re-reland: Remove register index/code indirection 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. Committed: https://crrev.com/80bc6f6e11f79524e3f1ad05579583adfd5f18b2 Cr-Commit-Position: refs/heads/master@{#30913} Committed: https://crrev.com/7b7a8205d9a00c678fb7a6e032a55fecbc1509cf Cr-Commit-Position: refs/heads/master@{#31075} Review URL: https://codereview.chromium.org/1287383003 Cr-Commit-Position: refs/heads/master@{#31087} --- BUILD.gn | 4 +- src/arm/assembler-arm-inl.h | 44 +-- src/arm/assembler-arm.cc | 40 +-- src/arm/assembler-arm.h | 250 ++++++-------- src/arm/constants-arm.cc | 11 - src/arm/deoptimizer-arm.cc | 18 +- src/arm/disasm-arm.cc | 2 +- src/arm/lithium-arm.cc | 7 +- src/arm/lithium-codegen-arm.cc | 14 +- src/arm/macro-assembler-arm.cc | 10 +- src/arm/macro-assembler-arm.h | 28 +- src/arm/simulator-arm.cc | 3 +- src/arm64/assembler-arm64.cc | 7 +- src/arm64/assembler-arm64.h | 182 +++------- src/arm64/constants-arm64.h | 6 - src/arm64/deoptimizer-arm64.cc | 8 +- src/arm64/lithium-arm64.cc | 7 +- src/arm64/lithium-codegen-arm64.cc | 8 +- src/arm64/macro-assembler-arm64.cc | 11 +- src/arm64/simulator-arm64.h | 6 - src/arm64/utils-arm64.h | 6 - src/assembler.cc | 32 ++ src/assembler.h | 2 - src/compiler/c-linkage.cc | 2 +- src/compiler/code-generator-impl.h | 5 +- src/compiler/code-generator.cc | 3 +- src/compiler/graph-visualizer.cc | 8 +- src/compiler/greedy-allocator.cc | 14 +- src/compiler/instruction-selector-impl.h | 15 +- src/compiler/instruction.cc | 20 +- src/compiler/instruction.h | 17 +- src/compiler/linkage.cc | 2 +- src/compiler/pipeline.cc | 1 + src/compiler/pipeline.h | 4 +- src/compiler/register-allocator-verifier.cc | 6 +- src/compiler/register-allocator.cc | 103 ++++-- src/compiler/register-allocator.h | 19 +- src/compiler/register-configuration.cc | 76 ----- src/compiler/register-configuration.h | 56 ---- src/deoptimizer.cc | 4 +- src/frames.cc | 6 +- src/hydrogen.cc | 4 +- src/ia32/assembler-ia32.h | 193 +++++------ src/ia32/code-stubs-ia32.h | 16 +- src/ia32/deoptimizer-ia32.cc | 30 +- src/ia32/lithium-codegen-ia32.cc | 14 +- src/ia32/lithium-gap-resolver-ia32.cc | 41 ++- src/ia32/lithium-gap-resolver-ia32.h | 4 +- src/ia32/lithium-ia32.cc | 7 +- src/ia32/macro-assembler-ia32.h | 22 +- src/lithium-allocator.cc | 93 +++--- src/lithium-allocator.h | 6 +- src/lithium.cc | 20 +- src/mips/assembler-mips-inl.h | 30 -- src/mips/assembler-mips.cc | 76 ++--- src/mips/assembler-mips.h | 313 +++++++----------- src/mips/deoptimizer-mips.cc | 28 +- src/mips/lithium-codegen-mips.cc | 8 +- src/mips/lithium-mips.cc | 7 +- src/mips/macro-assembler-mips.cc | 11 +- src/mips/macro-assembler-mips.h | 20 +- src/mips64/assembler-mips64-inl.h | 30 -- src/mips64/assembler-mips64.cc | 76 ++--- src/mips64/assembler-mips64.h | 307 +++++++---------- src/mips64/deoptimizer-mips64.cc | 28 +- src/mips64/lithium-codegen-mips64.cc | 8 +- src/mips64/lithium-mips64.cc | 7 +- src/mips64/macro-assembler-mips64.cc | 11 +- src/mips64/macro-assembler-mips64.h | 22 +- src/objects.cc | 2 +- src/register-configuration.cc | 146 ++++++++ src/register-configuration.h | 88 +++++ src/x64/assembler-x64.cc | 14 - src/x64/assembler-x64.h | 304 ++++++++--------- src/x64/code-stubs-x64.h | 16 +- src/x64/deoptimizer-x64.cc | 25 +- src/x64/lithium-codegen-x64.cc | 8 +- src/x64/lithium-x64.cc | 7 +- src/x64/macro-assembler-x64.cc | 20 +- src/x64/macro-assembler-x64.h | 22 +- src/x87/assembler-x87.h | 16 - test/cctest/compiler/test-gap-resolver.cc | 12 +- test/cctest/compiler/test-run-native-calls.cc | 143 +++++--- test/cctest/test-code-stubs-arm.cc | 22 +- test/cctest/test-code-stubs-arm64.cc | 20 +- test/cctest/test-code-stubs-ia32.cc | 24 +- test/cctest/test-code-stubs-mips.cc | 21 +- test/cctest/test-code-stubs-mips64.cc | 4 +- test/cctest/test-code-stubs-x64.cc | 14 +- .../compiler/instruction-selector-unittest.cc | 3 +- .../compiler/instruction-sequence-unittest.cc | 14 +- .../compiler/instruction-sequence-unittest.h | 2 +- .../compiler/register-allocator-unittest.cc | 3 +- tools/gyp/v8.gyp | 4 +- 94 files changed, 1634 insertions(+), 1819 deletions(-) delete mode 100644 src/compiler/register-configuration.cc delete mode 100644 src/compiler/register-configuration.h create mode 100644 src/register-configuration.cc create mode 100644 src/register-configuration.h diff --git a/BUILD.gn b/BUILD.gn index 5f4a127b51..8e4c414815 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -819,8 +819,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", @@ -1150,6 +1148,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", diff --git a/src/arm/assembler-arm-inl.h b/src/arm/assembler-arm-inl.h index ff44f40dc2..175a21df51 100644 --- a/src/arm/assembler-arm-inl.h +++ b/src/arm/assembler-arm-inl.h @@ -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. diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc index 50c707d2a0..dabccca7d1 100644 --- a/src/arm/assembler-arm.cc +++ b/src/arm/assembler-arm.cc @@ -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 @@ -398,26 +386,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; @@ -444,13 +432,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; @@ -626,21 +614,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; } diff --git a/src/arm/assembler-arm.h b/src/arm/assembler-arm.h index 2ada571327..6664c68905 100644 --- a/src/arm/assembler-arm.h +++ b/src/arm/assembler-arm.h @@ -50,6 +50,31 @@ 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; + enum Code { +#define REGISTER_CODE(R) kCode_##R, + GENERAL_REGISTERS(REGISTER_CODE) +#undef REGISTER_CODE + kAfterLast, + kCode_no_reg = -1 + }; - inline static int NumAllocatableRegisters(); - - static int ToAllocationIndex(Register reg) { - DCHECK(reg.code() < kMaxNumAllocatableRegisters); - return reg.code(); - } - - 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; }; diff --git a/src/arm/constants-arm.cc b/src/arm/constants-arm.cc index 9fefc3140a..915d9030e8 100644 --- a/src/arm/constants-arm.cc +++ b/src/arm/constants-arm.cc @@ -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 diff --git a/src/arm/deoptimizer-arm.cc b/src/arm/deoptimizer-arm.cc index 312bb00df3..91faa28bc7 100644 --- a/src/arm/deoptimizer-arm.cc +++ b/src/arm/deoptimizer-arm.cc @@ -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(frame->sp())); input_->SetRegister(fp.code(), reinterpret_cast(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); } diff --git a/src/arm/disasm-arm.cc b/src/arm/disasm-arm.cc index 0cc24e00af..9d86579f28 100644 --- a/src/arm/disasm-arm.cc +++ b/src/arm/disasm-arm.cc @@ -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(); } diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc index 4ccb020995..87cbf0996c 100644 --- a/src/arm/lithium-arm.cc +++ b/src/arm/lithium-arm.cc @@ -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()); } diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc index 3265ea9fd8..40a4a27c3f 100644 --- a/src/arm/lithium-codegen-arm.cc +++ b/src/arm/lithium-codegen-arm.cc @@ -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++; } @@ -404,13 +404,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); } diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc index 49802ba734..0356dd854b 100644 --- a/src/arm/macro-assembler-arm.cc +++ b/src/arm/macro-assembler-arm.cc @@ -11,6 +11,7 @@ #include "src/bootstrapper.h" #include "src/codegen.h" #include "src/debug/debug.h" +#include "src/register-configuration.h" #include "src/runtime/runtime.h" #include "src/arm/macro-assembler-arm.h" @@ -759,7 +760,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); } @@ -3578,8 +3580,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; } diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h index 97878184ec..6f176e6afc 100644 --- a/src/arm/macro-assembler-arm.h +++ b/src/arm/macro-assembler-arm.h @@ -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 { diff --git a/src/arm/simulator-arm.cc b/src/arm/simulator-arm.cc index 5da6204050..716e804e3a 100644 --- a/src/arm/simulator-arm.cc +++ b/src/arm/simulator-arm.cc @@ -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) { diff --git a/src/arm64/assembler-arm64.cc b/src/arm64/assembler-arm64.cc index 37a2f5a29d..0a1ecda9aa 100644 --- a/src/arm64/assembler-arm64.cc +++ b/src/arm64/assembler-arm64.cc @@ -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; } diff --git a/src/arm64/assembler-arm64.h b/src/arm64/assembler-arm64.h index 3fa8513485..049cb63c2b 100644 --- a/src/arm64/assembler-arm64.h +++ b/src/arm64/assembler-arm64.h @@ -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(NumAllocatableRegisters())); - // cp is the last allocatable register. - if (index == (static_cast(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(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 diff --git a/src/arm64/constants-arm64.h b/src/arm64/constants-arm64.h index db68e42889..8816cd0e2b 100644 --- a/src/arm64/constants-arm64.h +++ b/src/arm64/constants-arm64.h @@ -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. */ \ diff --git a/src/arm64/deoptimizer-arm64.cc b/src/arm64/deoptimizer-arm64.cc index 65fb93e53c..60409f6d26 100644 --- a/src/arm64/deoptimizer-arm64.cc +++ b/src/arm64/deoptimizer-arm64.cc @@ -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(frame->sp())); input_->SetRegister(fp.code(), reinterpret_cast(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. diff --git a/src/arm64/lithium-arm64.cc b/src/arm64/lithium-arm64.cc index e623718a1a..5cc5b9d592 100644 --- a/src/arm64/lithium-arm64.cc +++ b/src/arm64/lithium-arm64.cc @@ -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()); } diff --git a/src/arm64/lithium-codegen-arm64.cc b/src/arm64/lithium-codegen-arm64.cc index f0ebc38efc..3f84462c45 100644 --- a/src/arm64/lithium-codegen-arm64.cc +++ b/src/arm64/lithium-codegen-arm64.cc @@ -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++; @@ -1157,7 +1157,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()); } @@ -1181,7 +1181,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()); } diff --git a/src/arm64/macro-assembler-arm64.cc b/src/arm64/macro-assembler-arm64.cc index 5e8abe7215..c893dcad33 100644 --- a/src/arm64/macro-assembler-arm64.cc +++ b/src/arm64/macro-assembler-arm64.cc @@ -9,6 +9,7 @@ #include "src/bootstrapper.h" #include "src/codegen.h" #include "src/debug/debug.h" +#include "src/register-configuration.h" #include "src/runtime/runtime.h" #include "src/arm64/frames-arm64.h" @@ -3984,14 +3985,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(); } diff --git a/src/arm64/simulator-arm64.h b/src/arm64/simulator-arm64.h index a86a7add66..3d7c15cfd0 100644 --- a/src/arm64/simulator-arm64.h +++ b/src/arm64/simulator-arm64.h @@ -17,12 +17,6 @@ #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 { diff --git a/src/arm64/utils-arm64.h b/src/arm64/utils-arm64.h index df429736dc..1e1c0a33c2 100644 --- a/src/arm64/utils-arm64.h +++ b/src/arm64/utils-arm64.h @@ -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 { diff --git a/src/assembler.cc b/src/assembler.cc index dd05a07750..357d50d093 100644 --- a/src/assembler.cc +++ b/src/assembler.cc @@ -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" @@ -104,6 +105,37 @@ 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. diff --git a/src/assembler.h b/src/assembler.h index f218112ec9..4babeb53bb 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -1276,8 +1276,6 @@ class ConstantPoolBuilder BASE_EMBEDDED { PerTypeEntryInfo info_[ConstantPoolEntry::NUMBER_OF_TYPES]; }; - } // namespace internal } // namespace v8 - #endif // V8_ASSEMBLER_H_ diff --git a/src/compiler/c-linkage.cc b/src/compiler/c-linkage.cc index af5f813a30..1c91f7c118 100644 --- a/src/compiler/c-linkage.cc +++ b/src/compiler/c-linkage.cc @@ -15,7 +15,7 @@ namespace compiler { namespace { LinkageLocation regloc(Register reg) { - return LinkageLocation::ForRegister(Register::ToAllocationIndex(reg)); + return LinkageLocation::ForRegister(reg.code()); } diff --git a/src/compiler/code-generator-impl.h b/src/compiler/code-generator-impl.h index 83cbd22604..2e95bec0cc 100644 --- a/src/compiler/code-generator-impl.h +++ b/src/compiler/code-generator-impl.h @@ -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) { diff --git a/src/compiler/code-generator.cc b/src/compiler/code-generator.cc index 91602a02a3..f702cce1c3 100644 --- a/src/compiler/code-generator.cc +++ b/src/compiler/code-generator.cc @@ -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()); } } diff --git a/src/compiler/graph-visualizer.cc b/src/compiler/graph-visualizer.cc index 07ca04532b..47ca259e74 100644 --- a/src/compiler/graph-visualizer.cc +++ b/src/compiler/graph-visualizer.cc @@ -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(); diff --git a/src/compiler/greedy-allocator.cc b/src/compiler/greedy-allocator.cc index e0368bf366..5742801d69 100644 --- a/src/compiler/greedy-allocator.cc +++ b/src/compiler/greedy-allocator.cc @@ -249,7 +249,8 @@ void GreedyAllocator::TryAllocateGroup(LiveRangeGroup* group) { float eviction_weight = group_weight; int eviction_reg = -1; int free_reg = -1; - for (int reg = 0; reg < num_registers(); ++reg) { + for (int i = 0; i < num_allocatable_registers(); ++i) { + int reg = allocatable_register_code(i); float weight = GetMaximumConflictingWeight(reg, group, group_weight); if (weight == LiveRange::kInvalidWeight) { free_reg = reg; @@ -313,19 +314,20 @@ void GreedyAllocator::TryAllocateLiveRange(LiveRange* range) { // Seek either the first free register, or, from the set of registers // where the maximum conflict is lower than the candidate's weight, the one // with the smallest such weight. - for (int i = 0; i < num_registers(); i++) { + for (int i = 0; i < num_allocatable_registers(); i++) { + int reg = allocatable_register_code(i); // Skip unnecessarily re-visiting the hinted register, if any. - if (i == hinted_reg) continue; + if (reg == hinted_reg) continue; float max_conflict_weight = - GetMaximumConflictingWeight(i, range, competing_weight); + GetMaximumConflictingWeight(reg, range, competing_weight); if (max_conflict_weight == LiveRange::kInvalidWeight) { - free_reg = i; + free_reg = reg; break; } if (max_conflict_weight < range->weight() && max_conflict_weight < smallest_weight) { smallest_weight = max_conflict_weight; - evictable_reg = i; + evictable_reg = reg; } } } diff --git a/src/compiler/instruction-selector-impl.h b/src/compiler/instruction-selector-impl.h index 88283d4898..2ee099f9a8 100644 --- a/src/compiler/instruction-selector-impl.h +++ b/src/compiler/instruction-selector-impl.h @@ -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); } diff --git a/src/compiler/instruction.cc b/src/compiler/instruction.cc index 0fbb94979e..a7ed0e5f23 100644 --- a/src/compiler/instruction.cc +++ b/src/compiler/instruction.cc @@ -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()) { diff --git a/src/compiler/instruction.h b/src/compiler/instruction.h index a0718f3c21..fab184adf8 100644 --- a/src/compiler/instruction.h +++ b/src/compiler/instruction.h @@ -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(value_) >> IndexField::kShift; } + Register GetRegister() const { + DCHECK(REGISTER == allocated_kind() || DOUBLE_REGISTER == allocated_kind()); + return Register::from_code(static_cast(value_) >> + IndexField::kShift); + } + + DoubleRegister GetDoubleRegister() const { + DCHECK(REGISTER == allocated_kind() || DOUBLE_REGISTER == allocated_kind()); + return DoubleRegister::from_code(static_cast(value_) >> + IndexField::kShift); + } + AllocatedKind allocated_kind() const { return AllocatedKindField::decode(value_); } diff --git a/src/compiler/linkage.cc b/src/compiler/linkage.cc index af3decc5b5..7c124cde15 100644 --- a/src/compiler/linkage.cc +++ b/src/compiler/linkage.cc @@ -18,7 +18,7 @@ namespace compiler { namespace { LinkageLocation regloc(Register reg) { - return LinkageLocation::ForRegister(Register::ToAllocationIndex(reg)); + return LinkageLocation::ForRegister(reg.code()); } diff --git a/src/compiler/pipeline.cc b/src/compiler/pipeline.cc index 209ddfdf0d..3d153c1c0c 100644 --- a/src/compiler/pipeline.cc +++ b/src/compiler/pipeline.cc @@ -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" diff --git a/src/compiler/pipeline.h b/src/compiler/pipeline.h index 90c223f67e..d437c7e585 100644 --- a/src/compiler/pipeline.h +++ b/src/compiler/pipeline.h @@ -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 { diff --git a/src/compiler/register-allocator-verifier.cc b/src/compiler/register-allocator-verifier.cc index 0b775d29e1..3b595b3b45 100644 --- a/src/compiler/register-allocator-verifier.cc +++ b/src/compiler/register-allocator-verifier.cc @@ -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()); diff --git a/src/compiler/register-allocator.cc b/src/compiler/register-allocator.cc index 840c13b1a7..9fcb51d5ad 100644 --- a/src/compiler/register-allocator.cc +++ b/src/compiler/register-allocator.cc @@ -27,11 +27,26 @@ void RemoveElement(ZoneVector* 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(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(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(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& 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_allocatable_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_allocatable_registers(); ++i) { + int code = allocatable_register_code(i); + if (use_pos[code] > use_pos[reg]) { + reg = code; } } diff --git a/src/compiler/register-allocator.h b/src/compiler/register-allocator.h index 117ddedbcd..6747b8d305 100644 --- a/src/compiler/register-allocator.h +++ b/src/compiler/register-allocator.h @@ -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 allocatable_codes_; + ZoneVector allocatable_double_codes_; ZoneVector live_in_sets_; ZoneVector live_out_sets_; ZoneVector 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_allocatable_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 index ebe6cfe23c..0000000000 --- a/src/compiler/register-configuration.cc +++ /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::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 index f0d58735ba..0000000000 --- a/src/compiler/register-configuration.h +++ /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_ diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc index fdca98e90a..a2347287b8 100644 --- a/src/deoptimizer.cc +++ b/src/deoptimizer.cc @@ -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); } diff --git a/src/frames.cc b/src/frames.cc index 7e55833b45..7b847974fd 100644 --- a/src/frames.cc +++ b/src/frames.cc @@ -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. diff --git a/src/hydrogen.cc b/src/hydrogen.cc index 5093624dbd..211e4ba927 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -13526,10 +13526,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(); diff --git a/src/ia32/assembler-ia32.h b/src/ia32/assembler-ia32.h index fd5cf1ae82..82ab913546 100644 --- a/src/ia32/assembler-ia32.h +++ b/src/ia32/assembler-ia32.h @@ -42,10 +42,48 @@ #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; + enum Code { +#define REGISTER_CODE(R) kCode_##R, + GENERAL_REGISTERS(REGISTER_CODE) +#undef REGISTER_CODE + kAfterLast, + kCode_no_reg = -1 + }; - static inline const char* AllocationIndexToString(int index); - - 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 }; +#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}; -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]; -} +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 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; - } - - // 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(index >= 0 && index < kMaxNumAllocatableRegisters); - return from_code(index + 1); - } - - 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 diff --git a/src/ia32/code-stubs-ia32.h b/src/ia32/code-stubs-ia32.h index fc6ba80758..121d12fe74 100644 --- a/src/ia32/code-stubs-ia32.h +++ b/src/ia32/code-stubs-ia32.h @@ -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; diff --git a/src/ia32/deoptimizer-ia32.cc b/src/ia32/deoptimizer-ia32.cc index d804f630ea..756922a1ce 100644 --- a/src/ia32/deoptimizer-ia32.cc +++ b/src/ia32/deoptimizer-ia32.cc @@ -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(frame->sp())); input_->SetRegister(ebp.code(), reinterpret_cast(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)); } diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc index 8a87efeb72..b9286b7f64 100644 --- a/src/ia32/lithium-codegen-ia32.cc +++ b/src/ia32/lithium-codegen-ia32.cc @@ -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++; } @@ -514,13 +514,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); } diff --git a/src/ia32/lithium-gap-resolver-ia32.cc b/src/ia32/lithium-gap-resolver-ia32.cc index 0926a0f21a..655f4a2efb 100644 --- a/src/ia32/lithium-gap-resolver-ia32.cc +++ b/src/ia32/lithium-gap-resolver-ia32.cc @@ -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; } diff --git a/src/ia32/lithium-gap-resolver-ia32.h b/src/ia32/lithium-gap-resolver-ia32.h index 07a187820b..b52034f045 100644 --- a/src/ia32/lithium-gap-resolver-ia32.h +++ b/src/ia32/lithium-gap-resolver-ia32.h @@ -72,8 +72,8 @@ class LGapResolver final BASE_EMBEDDED { ZoneList 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. diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc index 884067b776..262e16bcbd 100644 --- a/src/ia32/lithium-ia32.cc +++ b/src/ia32/lithium-ia32.cc @@ -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()); } diff --git a/src/ia32/macro-assembler-ia32.h b/src/ia32/macro-assembler-ia32.h index 68c4435284..cf0a9a6fe9 100644 --- a/src/ia32/macro-assembler-ia32.h +++ b/src/ia32/macro-assembler-ia32.h @@ -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; diff --git a/src/lithium-allocator.cc b/src/lithium-allocator.cc index 36a12e75b3..7e34daab41 100644 --- a/src/lithium-allocator.cc +++ b/src/lithium-allocator.cc @@ -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(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); - for (int i = 0; i < num_registers_; i++) { + LifetimePosition free_until_pos[DoubleRegister::kMaxNumRegisters]; + + 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; } } diff --git a/src/lithium-allocator.h b/src/lithium-allocator.h index bd5127d66d..e52feaa74d 100644 --- a/src/lithium-allocator.h +++ b/src/lithium-allocator.h @@ -520,9 +520,8 @@ class LAllocator BASE_EMBEDDED { ZoneList live_ranges_; // Lists of live ranges - EmbeddedVector - fixed_live_ranges_; - EmbeddedVector + EmbeddedVector fixed_live_ranges_; + EmbeddedVector fixed_double_live_ranges_; ZoneList unhandled_live_ranges_; ZoneList 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_; diff --git a/src/lithium.cc b/src/lithium.cc index 7d37532ace..bc48a0a163 100644 --- a/src/lithium.cc +++ b/src/lithium.cc @@ -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; } diff --git a/src/mips/assembler-mips-inl.h b/src/mips/assembler-mips-inl.h index 01f33a560b..0d4576d85c 100644 --- a/src/mips/assembler-mips-inl.h +++ b/src/mips/assembler-mips-inl.h @@ -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. diff --git a/src/mips/assembler-mips.cc b/src/mips/assembler-mips.cc index 7fa4d5d66a..87abbe1b4d 100644 --- a/src/mips/assembler-mips.cc +++ b/src/mips/assembler-mips.cc @@ -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); } diff --git a/src/mips/assembler-mips.h b/src/mips/assembler-mips.h index 331e31054e..e4815eccec 100644 --- a/src/mips/assembler-mips.h +++ b/src/mips/assembler-mips.h @@ -47,6 +47,28 @@ 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; +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(); // 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). - // 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; - - 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; - } - - 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; +typedef DoubleRegister FPURegister; +typedef DoubleRegister FloatRegister; -const FPURegister no_freg = { -1 }; +const DoubleRegister 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 }; +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 }; diff --git a/src/mips/deoptimizer-mips.cc b/src/mips/deoptimizer-mips.cc index 974692495a..10cab306a2 100644 --- a/src/mips/deoptimizer-mips.cc +++ b/src/mips/deoptimizer-mips.cc @@ -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(frame->sp())); input_->SetRegister(fp.code(), reinterpret_cast(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)); } diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc index 3ab2316442..0857669e91 100644 --- a/src/mips/lithium-codegen-mips.cc +++ b/src/mips/lithium-codegen-mips.cc @@ -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++; @@ -402,12 +402,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); } diff --git a/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc index 42ecab4b8e..cafa4cfdbc 100644 --- a/src/mips/lithium-mips.cc +++ b/src/mips/lithium-mips.cc @@ -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()); } diff --git a/src/mips/macro-assembler-mips.cc b/src/mips/macro-assembler-mips.cc index e4cf09798b..a040ab5b0e 100644 --- a/src/mips/macro-assembler-mips.cc +++ b/src/mips/macro-assembler-mips.cc @@ -13,6 +13,7 @@ #include "src/codegen.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 { @@ -146,7 +147,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); } @@ -3681,7 +3682,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; } } @@ -5778,8 +5779,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; } diff --git a/src/mips/macro-assembler-mips.h b/src/mips/macro-assembler-mips.h index c8e21c421b..85ba81d82c 100644 --- a/src/mips/macro-assembler-mips.h +++ b/src/mips/macro-assembler-mips.h @@ -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; diff --git a/src/mips64/assembler-mips64-inl.h b/src/mips64/assembler-mips64-inl.h index 62dc2d3fa9..e35bf2facb 100644 --- a/src/mips64/assembler-mips64-inl.h +++ b/src/mips64/assembler-mips64-inl.h @@ -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. diff --git a/src/mips64/assembler-mips64.cc b/src/mips64/assembler-mips64.cc index cb5e164ff9..d5acd8d955 100644 --- a/src/mips64/assembler-mips64.cc +++ b/src/mips64/assembler-mips64.cc @@ -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); } diff --git a/src/mips64/assembler-mips64.h b/src/mips64/assembler-mips64.h index b1be0e8b39..775fab3946 100644 --- a/src/mips64/assembler-mips64.h +++ b/src/mips64/assembler-mips64.h @@ -47,6 +47,28 @@ 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,11 +94,7 @@ 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. #if defined(V8_TARGET_LITTLE_ENDIAN) @@ -89,117 +107,47 @@ struct Register { #error Unknown endianness #endif - inline static int NumAllocatableRegisters(); + enum Code { +#define REGISTER_CODE(R) kCode_##R, + GENERAL_REGISTERS(REGISTER_CODE) +#undef REGISTER_CODE + kAfterLast, + kCode_no_reg = -1 + }; - 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]; - } + 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); @@ -207,77 +155,72 @@ int ToNumber(Register reg); Register ToRegister(int num); // Coprocessor register. -struct FPURegister { - static const int kMaxNumRegisters = v8::internal::kNumFPURegisters; +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(); // 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). - // 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; - - 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; - } - - 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 @@ -287,43 +230,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; +typedef DoubleRegister FPURegister; +typedef DoubleRegister FloatRegister; -const FPURegister no_freg = { -1 }; +const DoubleRegister 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 }; +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. @@ -343,22 +286,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 }; diff --git a/src/mips64/deoptimizer-mips64.cc b/src/mips64/deoptimizer-mips64.cc index 958951a948..9c047efcc9 100644 --- a/src/mips64/deoptimizer-mips64.cc +++ b/src/mips64/deoptimizer-mips64.cc @@ -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(frame->sp())); input_->SetRegister(fp.code(), reinterpret_cast(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)); } diff --git a/src/mips64/lithium-codegen-mips64.cc b/src/mips64/lithium-codegen-mips64.cc index 5e1312e1b0..99b1950073 100644 --- a/src/mips64/lithium-codegen-mips64.cc +++ b/src/mips64/lithium-codegen-mips64.cc @@ -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++; @@ -385,12 +385,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); } diff --git a/src/mips64/lithium-mips64.cc b/src/mips64/lithium-mips64.cc index 4f2f161524..4595722fb4 100644 --- a/src/mips64/lithium-mips64.cc +++ b/src/mips64/lithium-mips64.cc @@ -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()); } diff --git a/src/mips64/macro-assembler-mips64.cc b/src/mips64/macro-assembler-mips64.cc index 26229c9d87..8f4db303d2 100644 --- a/src/mips64/macro-assembler-mips64.cc +++ b/src/mips64/macro-assembler-mips64.cc @@ -11,6 +11,7 @@ #include "src/codegen.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 { @@ -148,7 +149,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); } @@ -3761,7 +3762,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; } } @@ -6042,8 +6043,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; } diff --git a/src/mips64/macro-assembler-mips64.h b/src/mips64/macro-assembler-mips64.h index 68acbe3db3..2edc82950d 100644 --- a/src/mips64/macro-assembler-mips64.h +++ b/src/mips64/macro-assembler-mips64.h @@ -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; diff --git a/src/objects.cc b/src/objects.cc index 0f96bf4584..99c24d8aff 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -12252,7 +12252,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 index 0000000000..9b1c951f83 --- /dev/null +++ b/src/register-configuration.cc @@ -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::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 index 0000000000..f12bc7c07c --- /dev/null +++ b/src/register-configuration.h @@ -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_ diff --git a/src/x64/assembler-x64.cc b/src/x64/assembler-x64.cc index cb93ab878b..059b576bea 100644 --- a/src/x64/assembler-x64.cc +++ b/src/x64/assembler-x64.cc @@ -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 diff --git a/src/x64/assembler-x64.h b/src/x64/assembler-x64.h index 956e142c9e..f1ffcd29d6 100644 --- a/src/x64/assembler-x64.h +++ b/src/x64/assembler-x64.h @@ -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; + enum Code { +#define REGISTER_CODE(R) kCode_##R, + GENERAL_REGISTERS(REGISTER_CODE) +#undef REGISTER_CODE + kAfterLast, + kCode_no_reg = -1 + }; - 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; - } - - 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(); - } +#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) - static int ToAllocationIndex(XMMRegister reg) { - DCHECK(reg.code() != 0); - return reg.code() - 1; - } +#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) - static XMMRegister FromAllocationIndex(int index) { - DCHECK(0 <= index && index < kMaxNumAllocatableRegisters); - XMMRegister result = { index + 1 }; + +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 }; + +#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; - +typedef DoubleRegister XMMRegister; enum Condition { // any value < 0 is considered no_condition diff --git a/src/x64/code-stubs-x64.h b/src/x64/code-stubs-x64.h index 4e3715b0e1..d4f8b29dbc 100644 --- a/src/x64/code-stubs-x64.h +++ b/src/x64/code-stubs-x64.h @@ -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; diff --git a/src/x64/deoptimizer-x64.cc b/src/x64/deoptimizer-x64.cc index 72c92f0a39..8ec123a5da 100644 --- a/src/x64/deoptimizer-x64.cc +++ b/src/x64/deoptimizer-x64.cc @@ -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(frame->sp())); input_->SetRegister(rbp.code(), reinterpret_cast(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)); } diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc index b97dfa8ce7..b083f8abd4 100644 --- a/src/x64/lithium-codegen-x64.cc +++ b/src/x64/lithium-codegen-x64.cc @@ -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++; @@ -436,12 +436,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); } diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc index 9df3a7dabf..722ab01be2 100644 --- a/src/x64/lithium-x64.cc +++ b/src/x64/lithium-x64.cc @@ -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()); } diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc index ea837dca4b..f41da95da7 100644 --- a/src/x64/macro-assembler-x64.cc +++ b/src/x64/macro-assembler-x64.cc @@ -10,6 +10,7 @@ #include "src/codegen.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" @@ -729,7 +730,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), @@ -3710,12 +3712,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) { @@ -3758,8 +3762,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))); } } diff --git a/src/x64/macro-assembler-x64.h b/src/x64/macro-assembler-x64.h index 75d48858c4..b7183ff35d 100644 --- a/src/x64/macro-assembler-x64.h +++ b/src/x64/macro-assembler-x64.h @@ -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 diff --git a/src/x87/assembler-x87.h b/src/x87/assembler-x87.h index 2b5c7d2528..6d2c4e33db 100644 --- a/src/x87/assembler-x87.h +++ b/src/x87/assembler-x87.h @@ -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; diff --git a/test/cctest/compiler/test-gap-resolver.cc b/test/cctest/compiler/test-gap-resolver.cc index a081ddb8fe..7dade3df33 100644 --- a/test/cctest/compiler/test-gap-resolver.cc +++ b/test/cctest/compiler/test-gap-resolver.cc @@ -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, diff --git a/test/cctest/compiler/test-run-native-calls.cc b/test/cctest/compiler/test-run-native-calls.cc index bc6acf1bc9..af3748b8fd 100644 --- a/test/cctest/compiler/test-run-native-calls.cc +++ b/test/cctest/compiler/test-run-native-calls.cc @@ -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(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(desc, Build_Int32_WeightedSum, + Compute_Int32_WeightedSum, 257 + count); + } } } @@ -782,8 +798,10 @@ template 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::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::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::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(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++) { diff --git a/test/cctest/test-code-stubs-arm.cc b/test/cctest/test-code-stubs-arm.cc index a9856f5245..385718f486 100644 --- a/test/cctest/test-code-stubs-arm.cc +++ b/test/cctest/test-code-stubs-arm.cc @@ -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)); + } } } diff --git a/test/cctest/test-code-stubs-arm64.cc b/test/cctest/test-code-stubs-arm64.cc index 8f40c9052a..c7a6cdb4be 100644 --- a/test/cctest/test-code-stubs-arm64.cc +++ b/test/cctest/test-code-stubs-arm64.cc @@ -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); + } } } diff --git a/test/cctest/test-code-stubs-ia32.cc b/test/cctest/test-code-stubs-ia32.cc index ef44f5420b..e0f9a453ed 100644 --- a/test/cctest/test-code-stubs-ia32.cc +++ b/test/cctest/test-code-stubs-ia32.cc @@ -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)); + } } } diff --git a/test/cctest/test-code-stubs-mips.cc b/test/cctest/test-code-stubs-mips.cc index 10704efdca..de6203c0ff 100644 --- a/test/cctest/test-code-stubs-mips.cc +++ b/test/cctest/test-code-stubs-mips.cc @@ -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,11 +80,13 @@ 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) { + 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; + } } } @@ -108,10 +111,12 @@ ConvertDToIFunc MakeConvertDToIFuncTrampoline(Isolate* isolate, // Make sure no registers have been unexpectedly clobbered for (--reg_num; reg_num >= 2; --reg_num) { Register reg = Register::from_code(reg_num); - if (!reg.is(destination_reg)) { - __ lw(at, MemOperand(sp, 0)); - __ Assert(eq, kRegisterWasClobbered, reg, Operand(at)); - __ Addu(sp, sp, Operand(kPointerSize)); + if (reg.IsAllocatable()) { + if (!reg.is(destination_reg)) { + __ lw(at, MemOperand(sp, 0)); + __ Assert(eq, kRegisterWasClobbered, reg, Operand(at)); + __ Addu(sp, sp, Operand(kPointerSize)); + } } } diff --git a/test/cctest/test-code-stubs-mips64.cc b/test/cctest/test-code-stubs-mips64.cc index a8dd13cc07..fde2d07a9c 100644 --- a/test/cctest/test-code-stubs-mips64.cc +++ b/test/cctest/test-code-stubs-mips64.cc @@ -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); diff --git a/test/cctest/test-code-stubs-x64.cc b/test/cctest/test-code-stubs-x64.cc index 9eb153f651..8f22dd9fcf 100644 --- a/test/cctest/test-code-stubs-x64.cc +++ b/test/cctest/test-code-stubs-x64.cc @@ -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); diff --git a/test/unittests/compiler/instruction-selector-unittest.cc b/test/unittests/compiler/instruction-selector-unittest.cc index e14382e914..76bfe22171 100644 --- a/test/unittests/compiler/instruction-selector-unittest.cc +++ b/test/unittests/compiler/instruction-selector-unittest.cc @@ -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(); } diff --git a/test/unittests/compiler/instruction-sequence-unittest.cc b/test/unittests/compiler/instruction-sequence-unittest.cc index 65a7f299c5..51112a6470 100644 --- a/test/unittests/compiler/instruction-sequence-unittest.cc +++ b/test/unittests/compiler/instruction-sequence-unittest.cc @@ -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(); } diff --git a/test/unittests/compiler/instruction-sequence-unittest.h b/test/unittests/compiler/instruction-sequence-unittest.h index 54317ede21..e5e5139f97 100644 --- a/test/unittests/compiler/instruction-sequence-unittest.h +++ b/test/unittests/compiler/instruction-sequence-unittest.h @@ -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; diff --git a/test/unittests/compiler/register-allocator-unittest.cc b/test/unittests/compiler/register-allocator-unittest.cc index 75942b6854..c5ff90f301 100644 --- a/test/unittests/compiler/register-allocator-unittest.cc +++ b/test/unittests/compiler/register-allocator-unittest.cc @@ -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); } diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp index 2d14d037b6..e329b69d27 100644 --- a/tools/gyp/v8.gyp +++ b/tools/gyp/v8.gyp @@ -585,8 +585,6 @@ '../../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', @@ -914,6 +912,8 @@ '../../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',