Commit 72937ea4 authored by jgruber's avatar jgruber Committed by Commit Bot

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/1181023Reviewed-by: 's avatarSigurd Schneider <sigurds@chromium.org>
Reviewed-by: 's avatarJaroslav Sevcik <jarin@chromium.org>
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#55224}
parent f53e813e
......@@ -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")
......
......@@ -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();
}
......
......@@ -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);
......
......@@ -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);
......
......@@ -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;
......
......@@ -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);
......
......@@ -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);
......
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