From 86f530200220476a219651cc3587118f78224b7d Mon Sep 17 00:00:00 2001 From: "m.m.capewell@googlemail.com" Date: Mon, 24 Mar 2014 16:41:37 +0000 Subject: [PATCH] ARM64: push/pop registers in stubs for safepoints BUG= R=ulan@chromium.org Review URL: https://codereview.chromium.org/209933003 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20210 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm64/code-stubs-arm64.cc | 51 ++++++++++++++++++++++++++++++ src/arm64/code-stubs-arm64.h | 31 ++++++++++++++++++ src/arm64/lithium-codegen-arm64.h | 32 +++++++++++++------ src/arm64/macro-assembler-arm64.cc | 14 ++++++-- src/arm64/macro-assembler-arm64.h | 10 ++++-- src/code-stubs.h | 18 +++++++++-- 6 files changed, 140 insertions(+), 16 deletions(-) diff --git a/src/arm64/code-stubs-arm64.cc b/src/arm64/code-stubs-arm64.cc index 61b395fb9..b512e4259 100644 --- a/src/arm64/code-stubs-arm64.cc +++ b/src/arm64/code-stubs-arm64.cc @@ -1133,6 +1133,39 @@ void StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime( } +void StoreRegistersStateStub::Generate(MacroAssembler* masm) { + MacroAssembler::NoUseRealAbortsScope no_use_real_aborts(masm); + UseScratchRegisterScope temps(masm); + Register saved_lr = temps.UnsafeAcquire(to_be_pushed_lr()); + Register return_address = temps.AcquireX(); + __ Mov(return_address, lr); + // Restore lr with the value it had before the call to this stub (the value + // which must be pushed). + __ Mov(lr, saved_lr); + if (save_doubles_ == kSaveFPRegs) { + __ PushSafepointRegistersAndDoubles(); + } else { + __ PushSafepointRegisters(); + } + __ Ret(return_address); +} + + +void RestoreRegistersStateStub::Generate(MacroAssembler* masm) { + MacroAssembler::NoUseRealAbortsScope no_use_real_aborts(masm); + UseScratchRegisterScope temps(masm); + Register return_address = temps.AcquireX(); + // Preserve the return address (lr will be clobbered by the pop). + __ Mov(return_address, lr); + if (save_doubles_ == kSaveFPRegs) { + __ PopSafepointRegistersAndDoubles(); + } else { + __ PopSafepointRegisters(); + } + __ Ret(return_address); +} + + void MathPowStub::Generate(MacroAssembler* masm) { // Stack on entry: // jssp[0]: Exponent (as a tagged value). @@ -1394,10 +1427,28 @@ void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate); CreateAllocationSiteStub::GenerateAheadOfTime(isolate); BinaryOpICStub::GenerateAheadOfTime(isolate); + StoreRegistersStateStub::GenerateAheadOfTime(isolate); + RestoreRegistersStateStub::GenerateAheadOfTime(isolate); BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(isolate); } +void StoreRegistersStateStub::GenerateAheadOfTime(Isolate* isolate) { + StoreRegistersStateStub stub1(kDontSaveFPRegs); + stub1.GetCode(isolate); + StoreRegistersStateStub stub2(kSaveFPRegs); + stub2.GetCode(isolate); +} + + +void RestoreRegistersStateStub::GenerateAheadOfTime(Isolate* isolate) { + RestoreRegistersStateStub stub1(kDontSaveFPRegs); + stub1.GetCode(isolate); + RestoreRegistersStateStub stub2(kSaveFPRegs); + stub2.GetCode(isolate); +} + + void CodeStub::GenerateFPStubs(Isolate* isolate) { // Floating-point code doesn't get special handling in ARM64, so there's // nothing to do here. diff --git a/src/arm64/code-stubs-arm64.h b/src/arm64/code-stubs-arm64.h index e9862294a..7e09ffa57 100644 --- a/src/arm64/code-stubs-arm64.h +++ b/src/arm64/code-stubs-arm64.h @@ -77,6 +77,37 @@ class StringHelper : public AllStatic { }; +class StoreRegistersStateStub: public PlatformCodeStub { + public: + explicit StoreRegistersStateStub(SaveFPRegsMode with_fp) + : save_doubles_(with_fp) {} + + static Register to_be_pushed_lr() { return ip0; } + static void GenerateAheadOfTime(Isolate* isolate); + private: + Major MajorKey() { return StoreRegistersState; } + int MinorKey() { return (save_doubles_ == kSaveFPRegs) ? 1 : 0; } + SaveFPRegsMode save_doubles_; + + void Generate(MacroAssembler* masm); +}; + + +class RestoreRegistersStateStub: public PlatformCodeStub { + public: + explicit RestoreRegistersStateStub(SaveFPRegsMode with_fp) + : save_doubles_(with_fp) {} + + static void GenerateAheadOfTime(Isolate* isolate); + private: + Major MajorKey() { return RestoreRegistersState; } + int MinorKey() { return (save_doubles_ == kSaveFPRegs) ? 1 : 0; } + SaveFPRegsMode save_doubles_; + + void Generate(MacroAssembler* masm); +}; + + class RecordWriteStub: public PlatformCodeStub { public: // Stub to record the write of 'value' at 'address' in 'object'. diff --git a/src/arm64/lithium-codegen-arm64.h b/src/arm64/lithium-codegen-arm64.h index f42130518..d98e89ca1 100644 --- a/src/arm64/lithium-codegen-arm64.h +++ b/src/arm64/lithium-codegen-arm64.h @@ -377,14 +377,23 @@ class LCodeGen: public LCodeGenBase { ASSERT(codegen_->expected_safepoint_kind_ == Safepoint::kSimple); codegen_->expected_safepoint_kind_ = kind; + UseScratchRegisterScope temps(codegen_->masm_); + // Preserve the value of lr which must be saved on the stack (the call to + // the stub will clobber it). + Register to_be_pushed_lr = + temps.UnsafeAcquire(StoreRegistersStateStub::to_be_pushed_lr()); + codegen_->masm_->Mov(to_be_pushed_lr, lr); switch (codegen_->expected_safepoint_kind_) { - case Safepoint::kWithRegisters: - codegen_->masm_->PushSafepointRegisters(); + case Safepoint::kWithRegisters: { + StoreRegistersStateStub stub(kDontSaveFPRegs); + codegen_->masm_->CallStub(&stub); break; - case Safepoint::kWithRegistersAndDoubles: - codegen_->masm_->PushSafepointRegisters(); - codegen_->masm_->PushSafepointFPRegisters(); + } + case Safepoint::kWithRegistersAndDoubles: { + StoreRegistersStateStub stub(kSaveFPRegs); + codegen_->masm_->CallStub(&stub); break; + } default: UNREACHABLE(); } @@ -394,13 +403,16 @@ class LCodeGen: public LCodeGenBase { Safepoint::Kind kind = codegen_->expected_safepoint_kind_; ASSERT((kind & Safepoint::kWithRegisters) != 0); switch (kind) { - case Safepoint::kWithRegisters: - codegen_->masm_->PopSafepointRegisters(); + case Safepoint::kWithRegisters: { + RestoreRegistersStateStub stub(kDontSaveFPRegs); + codegen_->masm_->CallStub(&stub); break; - case Safepoint::kWithRegistersAndDoubles: - codegen_->masm_->PopSafepointFPRegisters(); - codegen_->masm_->PopSafepointRegisters(); + } + case Safepoint::kWithRegistersAndDoubles: { + RestoreRegistersStateStub stub(kSaveFPRegs); + codegen_->masm_->CallStub(&stub); break; + } default: UNREACHABLE(); } diff --git a/src/arm64/macro-assembler-arm64.cc b/src/arm64/macro-assembler-arm64.cc index a4108410b..1b85fbf6d 100644 --- a/src/arm64/macro-assembler-arm64.cc +++ b/src/arm64/macro-assembler-arm64.cc @@ -4163,15 +4163,17 @@ void MacroAssembler::PushSafepointRegisters() { } -void MacroAssembler::PushSafepointFPRegisters() { +void MacroAssembler::PushSafepointRegistersAndDoubles() { + PushSafepointRegisters(); PushCPURegList(CPURegList(CPURegister::kFPRegister, kDRegSizeInBits, FPRegister::kAllocatableFPRegisters)); } -void MacroAssembler::PopSafepointFPRegisters() { +void MacroAssembler::PopSafepointRegistersAndDoubles() { PopCPURegList(CPURegList(CPURegister::kFPRegister, kDRegSizeInBits, FPRegister::kAllocatableFPRegisters)); + PopSafepointRegisters(); } @@ -5120,6 +5122,14 @@ CPURegister UseScratchRegisterScope::AcquireNextAvailable( } +CPURegister UseScratchRegisterScope::UnsafeAcquire(CPURegList* available, + const CPURegister& reg) { + ASSERT(available->IncludesAliasOf(reg)); + available->Remove(reg); + return reg; +} + + #define __ masm-> diff --git a/src/arm64/macro-assembler-arm64.h b/src/arm64/macro-assembler-arm64.h index a54ed30a2..e676e2f7d 100644 --- a/src/arm64/macro-assembler-arm64.h +++ b/src/arm64/macro-assembler-arm64.h @@ -1728,8 +1728,8 @@ class MacroAssembler : public Assembler { void PushSafepointRegisters(); void PopSafepointRegisters(); - void PushSafepointFPRegisters(); - void PopSafepointFPRegisters(); + void PushSafepointRegistersAndDoubles(); + void PopSafepointRegistersAndDoubles(); // Store value in register src in the safepoint stack slot for register dst. void StoreToSafepointRegisterSlot(Register src, Register dst) { @@ -2215,11 +2215,17 @@ class UseScratchRegisterScope { FPRegister AcquireS() { return AcquireNextAvailable(availablefp_).S(); } FPRegister AcquireD() { return AcquireNextAvailable(availablefp_).D(); } + Register UnsafeAcquire(const Register& reg) { + return UnsafeAcquire(available_, reg); + } + Register AcquireSameSizeAs(const Register& reg); FPRegister AcquireSameSizeAs(const FPRegister& reg); private: static CPURegister AcquireNextAvailable(CPURegList* available); + static CPURegister UnsafeAcquire(CPURegList* available, + const CPURegister& reg); // Available scratch registers. CPURegList* available_; // kRegister diff --git a/src/code-stubs.h b/src/code-stubs.h index 25328fe5c..5a8894233 100644 --- a/src/code-stubs.h +++ b/src/code-stubs.h @@ -100,8 +100,8 @@ namespace internal { V(StringLength) \ V(KeyedStringLength) -// List of code stubs only used on ARM platforms. -#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_ARM64) +// List of code stubs only used on ARM 32 bits platforms. +#if V8_TARGET_ARCH_ARM #define CODE_STUB_LIST_ARM(V) \ V(GetProperty) \ V(SetProperty) \ @@ -111,6 +111,19 @@ namespace internal { #define CODE_STUB_LIST_ARM(V) #endif +// List of code stubs only used on ARM 64 bits platforms. +#if V8_TARGET_ARCH_ARM64 +#define CODE_STUB_LIST_ARM64(V) \ + V(GetProperty) \ + V(SetProperty) \ + V(InvokeBuiltin) \ + V(DirectCEntry) \ + V(StoreRegistersState) \ + V(RestoreRegistersState) +#else +#define CODE_STUB_LIST_ARM64(V) +#endif + // List of code stubs only used on MIPS platforms. #if V8_TARGET_ARCH_MIPS #define CODE_STUB_LIST_MIPS(V) \ @@ -126,6 +139,7 @@ namespace internal { #define CODE_STUB_LIST(V) \ CODE_STUB_LIST_ALL_PLATFORMS(V) \ CODE_STUB_LIST_ARM(V) \ + CODE_STUB_LIST_ARM64(V) \ CODE_STUB_LIST_MIPS(V) // Stub is base classes of all stubs. -- 2.34.1