Commit caff0ddd authored by Albert Mingkun Yang's avatar Albert Mingkun Yang Committed by Commit Bot

Allow CSA stubs to restrict the set of allocatable registers.

This is useful for the RecordWrite stub that can now specify the set
of allocatable registers in its call descriptor interface. 
During register allocation a custom register configuration is used to
ensure that the register are allocated from the given set.

This makes calling RecordWrite stub less expensive as we need to save/restore
only the allocatable registers instead all registers.

Bug: chromium:749486
Change-Id: If4d73f1fd525e480970ea92600fb811e63677eb5
Reviewed-on: https://chromium-review.googlesource.com/624734Reviewed-by: 's avatarJaroslav Sevcik <jarin@chromium.org>
Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Commit-Queue: Albert Mingkun Yang <albertnetymk@google.com>
Cr-Commit-Position: refs/heads/master@{#47577}
parent f71d6a19
...@@ -22,6 +22,13 @@ void CallInterfaceDescriptor::DefaultInitializePlatformSpecific( ...@@ -22,6 +22,13 @@ void CallInterfaceDescriptor::DefaultInitializePlatformSpecific(
default_stub_registers); default_stub_registers);
} }
void RecordWriteDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// TODO(albertnetymk): Use default for now; should call
// RestrictAllocatableRegisters like src/x64/interface-descriptors-x64.cc
DefaultInitializePlatformSpecific(data, kParameterCount);
}
const Register FastNewFunctionContextDescriptor::FunctionRegister() { const Register FastNewFunctionContextDescriptor::FunctionRegister() {
return r1; return r1;
} }
......
...@@ -22,6 +22,13 @@ void CallInterfaceDescriptor::DefaultInitializePlatformSpecific( ...@@ -22,6 +22,13 @@ void CallInterfaceDescriptor::DefaultInitializePlatformSpecific(
default_stub_registers); default_stub_registers);
} }
void RecordWriteDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// TODO(albertnetymk): Use default for now; should call
// RestrictAllocatableRegisters like src/x64/interface-descriptors-x64.cc
DefaultInitializePlatformSpecific(data, kParameterCount);
}
const Register FastNewFunctionContextDescriptor::FunctionRegister() { const Register FastNewFunctionContextDescriptor::FunctionRegister() {
return x1; return x1;
} }
......
...@@ -397,7 +397,7 @@ CallDescriptor* Linkage::GetStubCallDescriptor( ...@@ -397,7 +397,7 @@ CallDescriptor* Linkage::GetStubCallDescriptor(
kNoCalleeSaved, // callee-saved fp kNoCalleeSaved, // callee-saved fp
CallDescriptor::kCanUseRoots | // flags CallDescriptor::kCanUseRoots | // flags
flags, // flags flags, // flags
descriptor.DebugName(isolate)); descriptor.DebugName(isolate), descriptor.allocatable_registers());
} }
// static // static
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "src/compiler/frame.h" #include "src/compiler/frame.h"
#include "src/compiler/operator.h" #include "src/compiler/operator.h"
#include "src/globals.h" #include "src/globals.h"
#include "src/interface-descriptors.h"
#include "src/machine-type.h" #include "src/machine-type.h"
#include "src/reglist.h" #include "src/reglist.h"
#include "src/runtime/runtime.h" #include "src/runtime/runtime.h"
...@@ -198,7 +199,8 @@ class V8_EXPORT_PRIVATE CallDescriptor final ...@@ -198,7 +199,8 @@ class V8_EXPORT_PRIVATE CallDescriptor final
Operator::Properties properties, Operator::Properties properties,
RegList callee_saved_registers, RegList callee_saved_registers,
RegList callee_saved_fp_registers, Flags flags, RegList callee_saved_fp_registers, Flags flags,
const char* debug_name = "") const char* debug_name = "",
const RegList allocatable_registers = 0)
: kind_(kind), : kind_(kind),
target_type_(target_type), target_type_(target_type),
target_loc_(target_loc), target_loc_(target_loc),
...@@ -207,9 +209,9 @@ class V8_EXPORT_PRIVATE CallDescriptor final ...@@ -207,9 +209,9 @@ class V8_EXPORT_PRIVATE CallDescriptor final
properties_(properties), properties_(properties),
callee_saved_registers_(callee_saved_registers), callee_saved_registers_(callee_saved_registers),
callee_saved_fp_registers_(callee_saved_fp_registers), callee_saved_fp_registers_(callee_saved_fp_registers),
allocatable_registers_(allocatable_registers),
flags_(flags), flags_(flags),
debug_name_(debug_name) { debug_name_(debug_name) {}
}
// Returns the kind of this call. // Returns the kind of this call.
Kind kind() const { return kind_; } Kind kind() const { return kind_; }
...@@ -301,6 +303,12 @@ class V8_EXPORT_PRIVATE CallDescriptor final ...@@ -301,6 +303,12 @@ class V8_EXPORT_PRIVATE CallDescriptor final
int CalculateFixedFrameSize() const; int CalculateFixedFrameSize() const;
RegList AllocatableRegisters() const { return allocatable_registers_; }
bool HasRestrictedAllocatableRegisters() const {
return allocatable_registers_ != 0;
}
private: private:
friend class Linkage; friend class Linkage;
...@@ -312,6 +320,9 @@ class V8_EXPORT_PRIVATE CallDescriptor final ...@@ -312,6 +320,9 @@ class V8_EXPORT_PRIVATE CallDescriptor final
const Operator::Properties properties_; const Operator::Properties properties_;
const RegList callee_saved_registers_; const RegList callee_saved_registers_;
const RegList callee_saved_fp_registers_; const RegList callee_saved_fp_registers_;
// Non-zero value means restricting the set of allocatable registers for
// register allocator to use.
const RegList allocatable_registers_;
const Flags flags_; const Flags flags_;
const char* const debug_name_; const char* const debug_name_;
......
...@@ -1974,8 +1974,17 @@ bool PipelineImpl::ScheduleAndSelectInstructions(Linkage* linkage, ...@@ -1974,8 +1974,17 @@ bool PipelineImpl::ScheduleAndSelectInstructions(Linkage* linkage,
bool run_verifier = FLAG_turbo_verify_allocation; bool run_verifier = FLAG_turbo_verify_allocation;
// Allocate registers. // Allocate registers.
AllocateRegisters(RegisterConfiguration::Default(), call_descriptor, if (call_descriptor->HasRestrictedAllocatableRegisters()) {
run_verifier); auto registers = call_descriptor->AllocatableRegisters();
DCHECK(NumRegs(registers) > 0);
std::unique_ptr<const RegisterConfiguration> config;
config.reset(RegisterConfiguration::RestrictGeneralRegisters(registers));
AllocateRegisters(config.get(), call_descriptor, run_verifier);
} else {
AllocateRegisters(RegisterConfiguration::Default(), call_descriptor,
run_verifier);
}
Run<FrameElisionPhase>(); Run<FrameElisionPhase>();
if (data->compilation_failed()) { if (data->compilation_failed()) {
info()->AbortOptimization(kNotEnoughVirtualRegistersRegalloc); info()->AbortOptimization(kNotEnoughVirtualRegistersRegalloc);
......
...@@ -1602,6 +1602,8 @@ InstructionOperand* ConstraintBuilder::AllocateFixed( ...@@ -1602,6 +1602,8 @@ InstructionOperand* ConstraintBuilder::AllocateFixed(
operand->fixed_slot_index()); operand->fixed_slot_index());
} else if (operand->HasFixedRegisterPolicy()) { } else if (operand->HasFixedRegisterPolicy()) {
DCHECK(!IsFloatingPoint(rep)); DCHECK(!IsFloatingPoint(rep));
DCHECK(data()->config()->IsAllocatableGeneralCode(
operand->fixed_register_index()));
allocated = AllocatedOperand(AllocatedOperand::REGISTER, rep, allocated = AllocatedOperand(AllocatedOperand::REGISTER, rep,
operand->fixed_register_index()); operand->fixed_register_index());
} else if (operand->HasFixedFPRegisterPolicy()) { } else if (operand->HasFixedFPRegisterPolicy()) {
......
...@@ -242,6 +242,24 @@ class OutOfLineRecordWrite final : public OutOfLineCode { ...@@ -242,6 +242,24 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
mode_(mode), mode_(mode),
zone_(gen->zone()) {} zone_(gen->zone()) {}
void SaveRegisters(RegList registers) {
DCHECK(NumRegs(registers) > 0);
for (int i = 0; i < Register::kNumRegisters; ++i) {
if ((registers >> i) & 1u) {
__ pushq(Register::from_code(i));
}
}
}
void RestoreRegisters(RegList registers) {
DCHECK(NumRegs(registers) > 0);
for (int i = Register::kNumRegisters - 1; i >= 0; --i) {
if ((registers >> i) & 1u) {
__ popq(Register::from_code(i));
}
}
}
void Generate() final { void Generate() final {
if (mode_ > RecordWriteMode::kValueIsPointer) { if (mode_ > RecordWriteMode::kValueIsPointer) {
__ JumpIfSmi(value_, exit()); __ JumpIfSmi(value_, exit());
...@@ -249,20 +267,15 @@ class OutOfLineRecordWrite final : public OutOfLineCode { ...@@ -249,20 +267,15 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
__ CheckPageFlag(value_, scratch0_, __ CheckPageFlag(value_, scratch0_,
MemoryChunk::kPointersToHereAreInterestingMask, zero, MemoryChunk::kPointersToHereAreInterestingMask, zero,
exit()); exit());
RememberedSetAction const remembered_set_action =
mode_ > RecordWriteMode::kValueIsMap ? EMIT_REMEMBERED_SET
: OMIT_REMEMBERED_SET;
SaveFPRegsMode const save_fp_mode =
frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs;
__ leap(scratch1_, operand_); __ leap(scratch1_, operand_);
#ifdef V8_CSA_WRITE_BARRIER #ifdef V8_CSA_WRITE_BARRIER
(void)remembered_set_action;
// TODO(albertnetymk): Come up with a better way instead of blindly saving
// all registers.
__ PushCallerSaved(save_fp_mode);
Callable const callable = Callable const callable =
Builtins::CallableFor(__ isolate(), Builtins::kRecordWrite); Builtins::CallableFor(__ isolate(), Builtins::kRecordWrite);
RegList registers = callable.descriptor().allocatable_registers();
SaveRegisters(registers);
Register object_parameter(callable.descriptor().GetRegisterParameter( Register object_parameter(callable.descriptor().GetRegisterParameter(
RecordWriteDescriptor::kObject)); RecordWriteDescriptor::kObject));
Register slot_parameter(callable.descriptor().GetRegisterParameter( Register slot_parameter(callable.descriptor().GetRegisterParameter(
...@@ -280,8 +293,14 @@ class OutOfLineRecordWrite final : public OutOfLineCode { ...@@ -280,8 +293,14 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
ExternalReference::isolate_address(__ isolate())); ExternalReference::isolate_address(__ isolate()));
__ Call(callable.code(), RelocInfo::CODE_TARGET); __ Call(callable.code(), RelocInfo::CODE_TARGET);
__ PopCallerSaved(save_fp_mode); RestoreRegisters(registers);
#else #else
RememberedSetAction const remembered_set_action =
mode_ > RecordWriteMode::kValueIsMap ? EMIT_REMEMBERED_SET
: OMIT_REMEMBERED_SET;
SaveFPRegsMode const save_fp_mode =
frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs;
__ CallStubDelayed( __ CallStubDelayed(
new (zone_) RecordWriteStub(nullptr, object_, scratch0_, scratch1_, new (zone_) RecordWriteStub(nullptr, object_, scratch0_, scratch1_,
remembered_set_action, save_fp_mode)); remembered_set_action, save_fp_mode));
......
...@@ -20,6 +20,13 @@ void CallInterfaceDescriptor::DefaultInitializePlatformSpecific( ...@@ -20,6 +20,13 @@ void CallInterfaceDescriptor::DefaultInitializePlatformSpecific(
default_stub_registers); default_stub_registers);
} }
void RecordWriteDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// TODO(albertnetymk): Use default for now; should call
// RestrictAllocatableRegisters like src/x64/interface-descriptors-x64.cc
DefaultInitializePlatformSpecific(data, kParameterCount);
}
const Register FastNewFunctionContextDescriptor::FunctionRegister() { const Register FastNewFunctionContextDescriptor::FunctionRegister() {
return edi; return edi;
} }
......
...@@ -107,11 +107,6 @@ void RecordWriteDescriptor::InitializePlatformIndependent( ...@@ -107,11 +107,6 @@ void RecordWriteDescriptor::InitializePlatformIndependent(
machine_types); machine_types);
} }
void RecordWriteDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
DefaultInitializePlatformSpecific(data, kParameterCount);
}
void LoadDescriptor::InitializePlatformIndependent( void LoadDescriptor::InitializePlatformIndependent(
CallInterfaceDescriptorData* data) { CallInterfaceDescriptorData* data) {
// kReceiver, kName, kSlot // kReceiver, kName, kSlot
......
...@@ -87,7 +87,10 @@ class PlatformInterfaceDescriptor; ...@@ -87,7 +87,10 @@ class PlatformInterfaceDescriptor;
class V8_EXPORT_PRIVATE CallInterfaceDescriptorData { class V8_EXPORT_PRIVATE CallInterfaceDescriptorData {
public: public:
CallInterfaceDescriptorData() : register_param_count_(-1), param_count_(-1) {} CallInterfaceDescriptorData()
: register_param_count_(-1),
param_count_(-1),
allocatable_registers_(0) {}
// A copy of the passed in registers and param_representations is made // A copy of the passed in registers and param_representations is made
// and owned by the CallInterfaceDescriptorData. // and owned by the CallInterfaceDescriptorData.
...@@ -120,10 +123,24 @@ class V8_EXPORT_PRIVATE CallInterfaceDescriptorData { ...@@ -120,10 +123,24 @@ class V8_EXPORT_PRIVATE CallInterfaceDescriptorData {
return platform_specific_descriptor_; return platform_specific_descriptor_;
} }
void RestrictAllocatableRegisters(const Register* registers, int num) {
DCHECK(allocatable_registers_ == 0);
for (int i = 0; i < num; ++i) {
allocatable_registers_ |= registers[i].bit();
}
DCHECK(NumRegs(allocatable_registers_) > 0);
}
RegList allocatable_registers() const { return allocatable_registers_; }
private: private:
int register_param_count_; int register_param_count_;
int param_count_; int param_count_;
// Specifying the set of registers that could be used by the register
// allocator. Currently, it's only used by RecordWrite code stub.
RegList allocatable_registers_;
// The Register params are allocated dynamically by the // The Register params are allocated dynamically by the
// InterfaceDescriptor, and freed on destruction. This is because static // InterfaceDescriptor, and freed on destruction. This is because static
// arrays of Registers cause creation of runtime static initializers // arrays of Registers cause creation of runtime static initializers
...@@ -179,6 +196,10 @@ class V8_EXPORT_PRIVATE CallInterfaceDescriptor { ...@@ -179,6 +196,10 @@ class V8_EXPORT_PRIVATE CallInterfaceDescriptor {
return data()->platform_specific_descriptor(); return data()->platform_specific_descriptor();
} }
RegList allocatable_registers() const {
return data()->allocatable_registers();
}
static const Register ContextRegister(); static const Register ContextRegister();
const char* DebugName(Isolate* isolate) const; const char* DebugName(Isolate* isolate) const;
......
...@@ -20,6 +20,13 @@ void CallInterfaceDescriptor::DefaultInitializePlatformSpecific( ...@@ -20,6 +20,13 @@ void CallInterfaceDescriptor::DefaultInitializePlatformSpecific(
default_stub_registers); default_stub_registers);
} }
void RecordWriteDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// TODO(albertnetymk): Use default for now; should call
// RestrictAllocatableRegisters like src/x64/interface-descriptors-x64.cc
DefaultInitializePlatformSpecific(data, kParameterCount);
}
const Register FastNewFunctionContextDescriptor::FunctionRegister() { const Register FastNewFunctionContextDescriptor::FunctionRegister() {
return a1; return a1;
} }
......
...@@ -20,6 +20,13 @@ void CallInterfaceDescriptor::DefaultInitializePlatformSpecific( ...@@ -20,6 +20,13 @@ void CallInterfaceDescriptor::DefaultInitializePlatformSpecific(
default_stub_registers); default_stub_registers);
} }
void RecordWriteDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// TODO(albertnetymk): Use default for now; should call
// RestrictAllocatableRegisters like src/x64/interface-descriptors-x64.cc
DefaultInitializePlatformSpecific(data, kParameterCount);
}
const Register FastNewFunctionContextDescriptor::FunctionRegister() { const Register FastNewFunctionContextDescriptor::FunctionRegister() {
return a1; return a1;
} }
......
...@@ -20,6 +20,13 @@ void CallInterfaceDescriptor::DefaultInitializePlatformSpecific( ...@@ -20,6 +20,13 @@ void CallInterfaceDescriptor::DefaultInitializePlatformSpecific(
default_stub_registers); default_stub_registers);
} }
void RecordWriteDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// TODO(albertnetymk): Use default for now; should call
// RestrictAllocatableRegisters like src/x64/interface-descriptors-x64.cc
DefaultInitializePlatformSpecific(data, kParameterCount);
}
const Register FastNewFunctionContextDescriptor::FunctionRegister() { const Register FastNewFunctionContextDescriptor::FunctionRegister() {
return r4; return r4;
} }
......
...@@ -64,52 +64,75 @@ STATIC_ASSERT(RegisterConfiguration::kMaxFPRegisters >= ...@@ -64,52 +64,75 @@ STATIC_ASSERT(RegisterConfiguration::kMaxFPRegisters >=
STATIC_ASSERT(RegisterConfiguration::kMaxFPRegisters >= STATIC_ASSERT(RegisterConfiguration::kMaxFPRegisters >=
Simd128Register::kMaxNumRegisters); Simd128Register::kMaxNumRegisters);
class ArchDefaultRegisterConfiguration : public RegisterConfiguration { static int get_num_allocatable_general_registers() {
public: return
ArchDefaultRegisterConfiguration()
: RegisterConfiguration(
Register::kNumRegisters, DoubleRegister::kMaxNumRegisters,
#if V8_TARGET_ARCH_IA32 #if V8_TARGET_ARCH_IA32
kMaxAllocatableGeneralRegisterCount, kMaxAllocatableGeneralRegisterCount;
kMaxAllocatableDoubleRegisterCount,
#elif V8_TARGET_ARCH_X64 #elif V8_TARGET_ARCH_X64
kMaxAllocatableGeneralRegisterCount, kMaxAllocatableGeneralRegisterCount;
kMaxAllocatableDoubleRegisterCount,
#elif V8_TARGET_ARCH_ARM #elif V8_TARGET_ARCH_ARM
kMaxAllocatableGeneralRegisterCount, kMaxAllocatableGeneralRegisterCount;
CpuFeatures::IsSupported(VFP32DREGS)
? kMaxAllocatableDoubleRegisterCount
: (ALLOCATABLE_NO_VFP32_DOUBLE_REGISTERS(REGISTER_COUNT) 0),
#elif V8_TARGET_ARCH_ARM64 #elif V8_TARGET_ARCH_ARM64
kMaxAllocatableGeneralRegisterCount, kMaxAllocatableGeneralRegisterCount;
kMaxAllocatableDoubleRegisterCount,
#elif V8_TARGET_ARCH_MIPS #elif V8_TARGET_ARCH_MIPS
kMaxAllocatableGeneralRegisterCount, kMaxAllocatableGeneralRegisterCount;
kMaxAllocatableDoubleRegisterCount,
#elif V8_TARGET_ARCH_MIPS64 #elif V8_TARGET_ARCH_MIPS64
kMaxAllocatableGeneralRegisterCount, kMaxAllocatableGeneralRegisterCount;
kMaxAllocatableDoubleRegisterCount,
#elif V8_TARGET_ARCH_PPC #elif V8_TARGET_ARCH_PPC
kMaxAllocatableGeneralRegisterCount, kMaxAllocatableGeneralRegisterCount;
kMaxAllocatableDoubleRegisterCount,
#elif V8_TARGET_ARCH_S390 #elif V8_TARGET_ARCH_S390
kMaxAllocatableGeneralRegisterCount, kMaxAllocatableGeneralRegisterCount;
kMaxAllocatableDoubleRegisterCount,
#else #else
#error Unsupported target architecture. #error Unsupported target architecture.
#endif #endif
kAllocatableGeneralCodes, }
static int get_num_allocatable_double_registers() {
return
#if V8_TARGET_ARCH_IA32
kMaxAllocatableDoubleRegisterCount;
#elif V8_TARGET_ARCH_X64
kMaxAllocatableDoubleRegisterCount;
#elif V8_TARGET_ARCH_ARM
CpuFeatures::IsSupported(VFP32DREGS)
? kMaxAllocatableDoubleRegisterCount
: (ALLOCATABLE_NO_VFP32_DOUBLE_REGISTERS(REGISTER_COUNT) 0);
#elif V8_TARGET_ARCH_ARM64
kMaxAllocatableDoubleRegisterCount;
#elif V8_TARGET_ARCH_MIPS
kMaxAllocatableDoubleRegisterCount;
#elif V8_TARGET_ARCH_MIPS64
kMaxAllocatableDoubleRegisterCount;
#elif V8_TARGET_ARCH_PPC
kMaxAllocatableDoubleRegisterCount;
#elif V8_TARGET_ARCH_S390
kMaxAllocatableDoubleRegisterCount;
#else
#error Unsupported target architecture.
#endif
}
static const int* get_allocatable_double_codes() {
return
#if V8_TARGET_ARCH_ARM #if V8_TARGET_ARCH_ARM
CpuFeatures::IsSupported(VFP32DREGS) CpuFeatures::IsSupported(VFP32DREGS) ? kAllocatableDoubleCodes
? kAllocatableDoubleCodes : kAllocatableNoVFP32DoubleCodes;
: kAllocatableNoVFP32DoubleCodes,
#else #else
kAllocatableDoubleCodes, kAllocatableDoubleCodes;
#endif #endif
}
class ArchDefaultRegisterConfiguration : public RegisterConfiguration {
public:
ArchDefaultRegisterConfiguration()
: RegisterConfiguration(
Register::kNumRegisters, DoubleRegister::kMaxNumRegisters,
get_num_allocatable_general_registers(),
get_num_allocatable_double_registers(), kAllocatableGeneralCodes,
get_allocatable_double_codes(),
kSimpleFPAliasing ? AliasingKind::OVERLAP : AliasingKind::COMBINE, kSimpleFPAliasing ? AliasingKind::OVERLAP : AliasingKind::COMBINE,
kGeneralRegisterNames, kFloatRegisterNames, kDoubleRegisterNames, kGeneralRegisterNames, kFloatRegisterNames, kDoubleRegisterNames,
kSimd128RegisterNames) { kSimd128RegisterNames) {}
}
}; };
struct RegisterConfigurationInitializer { struct RegisterConfigurationInitializer {
...@@ -122,12 +145,74 @@ static base::LazyInstance<ArchDefaultRegisterConfiguration, ...@@ -122,12 +145,74 @@ static base::LazyInstance<ArchDefaultRegisterConfiguration,
RegisterConfigurationInitializer>::type RegisterConfigurationInitializer>::type
kDefaultRegisterConfiguration = LAZY_INSTANCE_INITIALIZER; kDefaultRegisterConfiguration = LAZY_INSTANCE_INITIALIZER;
// RestrictedRegisterConfiguration uses the subset of allocatable general
// registers the architecture support, which results into generating assembly
// to use less registers. Currently, it's only used by RecordWrite code stub.
class RestrictedRegisterConfiguration : public RegisterConfiguration {
public:
RestrictedRegisterConfiguration(
int num_allocatable_general_registers,
std::unique_ptr<int[]> allocatable_general_register_codes,
std::unique_ptr<char const* []> allocatable_general_register_names)
: RegisterConfiguration(
Register::kNumRegisters, DoubleRegister::kMaxNumRegisters,
num_allocatable_general_registers,
get_num_allocatable_double_registers(),
allocatable_general_register_codes.get(),
get_allocatable_double_codes(),
kSimpleFPAliasing ? AliasingKind::OVERLAP : AliasingKind::COMBINE,
allocatable_general_register_names.get(), kFloatRegisterNames,
kDoubleRegisterNames, kSimd128RegisterNames),
allocatable_general_register_codes_(
std::move(allocatable_general_register_codes)),
allocatable_general_register_names_(
std::move(allocatable_general_register_names)) {
for (int i = 0; i < num_allocatable_general_registers; ++i) {
DCHECK(
IsAllocatableGeneralRegister(allocatable_general_register_codes_[i]));
}
}
bool IsAllocatableGeneralRegister(int code) {
for (int i = 0; i < kMaxAllocatableGeneralRegisterCount; ++i) {
if (code == kAllocatableGeneralCodes[i]) {
return true;
}
}
return false;
}
private:
std::unique_ptr<int[]> allocatable_general_register_codes_;
std::unique_ptr<char const* []> allocatable_general_register_names_;
};
} // namespace } // namespace
const RegisterConfiguration* RegisterConfiguration::Default() { const RegisterConfiguration* RegisterConfiguration::Default() {
return &kDefaultRegisterConfiguration.Get(); return &kDefaultRegisterConfiguration.Get();
} }
const RegisterConfiguration* RegisterConfiguration::RestrictGeneralRegisters(
RegList registers) {
int num = NumRegs(registers);
std::unique_ptr<int[]> codes{new int[num]};
std::unique_ptr<char const* []> names { new char const*[num] };
int counter = 0;
for (int i = 0; i < Default()->num_allocatable_general_registers(); ++i) {
auto reg = Register::from_code(Default()->GetAllocatableGeneralCode(i));
if (reg.bit() & registers) {
DCHECK(counter < num);
codes[counter] = reg.code();
names[counter] = Default()->GetGeneralRegisterName(i);
counter++;
}
}
return new RestrictedRegisterConfiguration(num, std::move(codes),
std::move(names));
}
RegisterConfiguration::RegisterConfiguration( RegisterConfiguration::RegisterConfiguration(
int num_general_registers, int num_double_registers, int num_general_registers, int num_double_registers,
int num_allocatable_general_registers, int num_allocatable_double_registers, int num_allocatable_general_registers, int num_allocatable_double_registers,
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "src/base/macros.h" #include "src/base/macros.h"
#include "src/globals.h" #include "src/globals.h"
#include "src/machine-type.h" #include "src/machine-type.h"
#include "src/reglist.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -30,6 +31,9 @@ class V8_EXPORT_PRIVATE RegisterConfiguration { ...@@ -30,6 +31,9 @@ class V8_EXPORT_PRIVATE RegisterConfiguration {
// Default RegisterConfigurations for the target architecture. // Default RegisterConfigurations for the target architecture.
static const RegisterConfiguration* Default(); static const RegisterConfiguration* Default();
static const RegisterConfiguration* RestrictGeneralRegisters(
RegList registers);
RegisterConfiguration(int num_general_registers, int num_double_registers, RegisterConfiguration(int num_general_registers, int num_double_registers,
int num_allocatable_general_registers, int num_allocatable_general_registers,
int num_allocatable_double_registers, int num_allocatable_double_registers,
...@@ -132,6 +136,8 @@ class V8_EXPORT_PRIVATE RegisterConfiguration { ...@@ -132,6 +136,8 @@ class V8_EXPORT_PRIVATE RegisterConfiguration {
bool AreAliases(MachineRepresentation rep, int index, bool AreAliases(MachineRepresentation rep, int index,
MachineRepresentation other_rep, int other_index) const; MachineRepresentation other_rep, int other_index) const;
virtual ~RegisterConfiguration() {}
private: private:
const int num_general_registers_; const int num_general_registers_;
int num_float_registers_; int num_float_registers_;
......
...@@ -20,6 +20,13 @@ void CallInterfaceDescriptor::DefaultInitializePlatformSpecific( ...@@ -20,6 +20,13 @@ void CallInterfaceDescriptor::DefaultInitializePlatformSpecific(
default_stub_registers); default_stub_registers);
} }
void RecordWriteDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// TODO(albertnetymk): Use default for now; should call
// RestrictAllocatableRegisters like src/x64/interface-descriptors-x64.cc
DefaultInitializePlatformSpecific(data, kParameterCount);
}
const Register FastNewFunctionContextDescriptor::FunctionRegister() { const Register FastNewFunctionContextDescriptor::FunctionRegister() {
return r3; return r3;
} }
......
...@@ -20,6 +20,19 @@ void CallInterfaceDescriptor::DefaultInitializePlatformSpecific( ...@@ -20,6 +20,19 @@ void CallInterfaceDescriptor::DefaultInitializePlatformSpecific(
default_stub_registers); default_stub_registers);
} }
void RecordWriteDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
const Register default_stub_registers[] = {arg_reg_1, arg_reg_2, arg_reg_3,
arg_reg_4, kReturnRegister0};
data->RestrictAllocatableRegisters(default_stub_registers,
arraysize(default_stub_registers));
CHECK_LE(static_cast<size_t>(kParameterCount),
arraysize(default_stub_registers));
data->InitializePlatformSpecific(kParameterCount, default_stub_registers);
}
const Register FastNewFunctionContextDescriptor::FunctionRegister() { const Register FastNewFunctionContextDescriptor::FunctionRegister() {
return rdi; return rdi;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment