Register alloc config for kRootRegister on ia32

This CL prepares the way for adding a root register on ia32. The new
register allocation configuration PreserveRootIA32 treats
kRootRegister as an unallocatable register.

Note that kRootRegister (on ia32) is still completely unused,
unallocated, and may be clobbered at many points. This is left to
future work.

Bug: v8:6666
Change-Id: I4aacdf9c3bb365d6ed49fea8f013f79b7b1f0a98
Reviewed-on: https://chromium-review.googlesource.com/1181023
Reviewed-by: Sigurd Schneider <sigurds@chromium.org>
Reviewed-by: Jaroslav Sevcik <jarin@chromium.org>
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#55224}
This commit is contained in:
jgruber 2018-08-20 14:01:04 +02:00 committed by Commit Bot
parent f53e813e29
commit 72937ea4a8
7 changed files with 93 additions and 1 deletions

View File

@ -192,6 +192,10 @@ if (v8_check_microtasks_scopes_consistency == "") {
assert(!v8_enable_embedded_builtins || v8_use_snapshot,
"Embedded builtins only work with snapshots")
assert(
v8_current_cpu != "x86" || !v8_enable_embedded_builtins ||
!v8_untrusted_code_mitigations,
"Embedded builtins on ia32 and untrusted code mitigations are incompatible")
assert(!v8_enable_embedded_bytecode_handlers || v8_enable_embedded_builtins,
"Embedded bytecode handlers only work with embedded builtins")

View File

@ -314,6 +314,7 @@ bool Builtins::IsLazy(int index) {
// static
bool Builtins::IsIsolateIndependent(int index) {
DCHECK(IsBuiltinId(index));
#ifndef V8_TARGET_ARCH_IA32
switch (index) {
// TODO(jgruber): There's currently two blockers for moving
// InterpreterEntryTrampoline into the binary:
@ -332,6 +333,15 @@ bool Builtins::IsIsolateIndependent(int index) {
default:
return true;
}
#else // V8_TARGET_ARCH_IA32
// TODO(jgruber, v8:6666): Implement support.
// ia32 is a work-in-progress. This will let us make builtins
// isolate-independent one-by-one.
switch (index) {
default:
return false;
}
#endif // V8_TARGET_ARCH_IA32
UNREACHABLE();
}

View File

@ -89,7 +89,9 @@ void BuiltinsConstantsTableBuilder::Finalize() {
isolate_->heap()->builtins_constants_table());
DCHECK(isolate_->serializer_enabled());
DCHECK_LT(0, map_.size());
// An empty map means there's nothing to do.
if (map_.size() == 0) return;
Handle<FixedArray> table =
isolate_->factory()->NewFixedArray(map_.size(), TENURED);

View File

@ -303,6 +303,10 @@ class PipelineData {
return jump_optimization_info_;
}
const AssemblerOptions& assembler_options() const {
return assembler_options_;
}
CodeTracer* GetCodeTracer() const {
return wasm_engine_ == nullptr ? isolate_->GetCodeTracer()
: wasm_engine_->GetCodeTracer();
@ -2402,6 +2406,17 @@ bool PipelineImpl::SelectInstructions(Linkage* linkage) {
PoisoningMitigationLevel::kDontPoison) {
AllocateRegisters(RegisterConfiguration::Poisoning(), call_descriptor,
run_verifier);
#if defined(V8_TARGET_ARCH_IA32) && defined(V8_EMBEDDED_BUILTINS)
} else if (data_->assembler_options().isolate_independent_code) {
// TODO(v8:6666): Extend support to all builtins and user code. Ensure that
// it is mutually exclusive with the Poisoning configuration above; and that
// it cooperates with restricted allocatable registers above.
static_assert(kRootRegister == kSpeculationPoisonRegister);
CHECK_IMPLIES(FLAG_embedded_builtins, !FLAG_branch_load_poisoning);
CHECK_IMPLIES(FLAG_embedded_builtins, !FLAG_untrusted_code_mitigations);
AllocateRegisters(RegisterConfiguration::PreserveRootIA32(),
call_descriptor, run_verifier);
#endif // V8_TARGET_ARCH_IA32
} else {
AllocateRegisters(RegisterConfiguration::Default(), call_descriptor,
run_verifier);

View File

@ -38,6 +38,9 @@ constexpr Register kRuntimeCallFunctionRegister = ebx;
constexpr Register kRuntimeCallArgCountRegister = eax;
constexpr Register kWasmInstanceRegister = esi;
// TODO(v8:6666): Implement full support.
constexpr Register kRootRegister = ebx;
// Convenience for platform-independent signatures. We do not normally
// distinguish memory operands from other operands on ia32.
typedef Operand MemOperand;

View File

@ -166,6 +166,55 @@ static base::LazyInstance<ArchDefaultPoisoningRegisterConfiguration,
PoisoningRegisterConfigurationInitializer>::type
kDefaultPoisoningRegisterConfiguration = LAZY_INSTANCE_INITIALIZER;
#if defined(V8_TARGET_ARCH_IA32) && defined(V8_EMBEDDED_BUILTINS)
// Allocatable registers with the root register removed.
// TODO(v8:6666): Once all builtins have been migrated, we could remove this
// configuration and remove kRootRegister from ALLOCATABLE_GENERAL_REGISTERS
// instead.
class ArchPreserveRootIA32RegisterConfiguration : public RegisterConfiguration {
public:
ArchPreserveRootIA32RegisterConfiguration()
: RegisterConfiguration(
Register::kNumRegisters, DoubleRegister::kNumRegisters,
kMaxAllocatableGeneralRegisterCount - 1,
get_num_allocatable_double_registers(),
InitializeGeneralRegisterCodes(), get_allocatable_double_codes(),
kSimpleFPAliasing ? AliasingKind::OVERLAP : AliasingKind::COMBINE,
kGeneralRegisterNames, kFloatRegisterNames, kDoubleRegisterNames,
kSimd128RegisterNames) {}
private:
static const int* InitializeGeneralRegisterCodes() {
int filtered_index = 0;
for (int i = 0; i < kMaxAllocatableGeneralRegisterCount; ++i) {
if (kAllocatableGeneralCodes[i] != kRootRegister.code()) {
allocatable_general_codes_[filtered_index] =
kAllocatableGeneralCodes[i];
filtered_index++;
}
}
DCHECK_EQ(filtered_index, kMaxAllocatableGeneralRegisterCount - 1);
return allocatable_general_codes_;
}
static int
allocatable_general_codes_[kMaxAllocatableGeneralRegisterCount - 1];
};
int ArchPreserveRootIA32RegisterConfiguration::allocatable_general_codes_
[kMaxAllocatableGeneralRegisterCount - 1];
struct PreserveRootIA32RegisterConfigurationInitializer {
static void Construct(void* config) {
new (config) ArchPreserveRootIA32RegisterConfiguration();
}
};
static base::LazyInstance<ArchPreserveRootIA32RegisterConfiguration,
PreserveRootIA32RegisterConfigurationInitializer>::
type kPreserveRootIA32RegisterConfiguration = LAZY_INSTANCE_INITIALIZER;
#endif // defined(V8_TARGET_ARCH_IA32) && defined(V8_EMBEDDED_BUILTINS)
// 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.
@ -218,6 +267,12 @@ const RegisterConfiguration* RegisterConfiguration::Poisoning() {
return &kDefaultPoisoningRegisterConfiguration.Get();
}
#if defined(V8_TARGET_ARCH_IA32) && defined(V8_EMBEDDED_BUILTINS)
const RegisterConfiguration* RegisterConfiguration::PreserveRootIA32() {
return &kPreserveRootIA32RegisterConfiguration.Get();
}
#endif // defined(V8_TARGET_ARCH_IA32) && defined(V8_EMBEDDED_BUILTINS)
const RegisterConfiguration* RegisterConfiguration::RestrictGeneralRegisters(
RegList registers) {
int num = NumRegs(registers);

View File

@ -34,6 +34,9 @@ class V8_EXPORT_PRIVATE RegisterConfiguration {
// Register configuration with reserved masking register.
static const RegisterConfiguration* Poisoning();
// Register configuration with reserved root register on ia32.
static const RegisterConfiguration* PreserveRootIA32();
static const RegisterConfiguration* RestrictGeneralRegisters(
RegList registers);