From f1f6d3095acbdef44576ef8f2bcb5da86104816a Mon Sep 17 00:00:00 2001 From: "rmcilroy@chromium.org" Date: Fri, 14 Mar 2014 15:11:58 +0000 Subject: [PATCH] Fix deoptimization for out-of-line constant pool. Ensure that the stack contains the correct constant pool pointer when a function deopts. This CL depends on https://codereview.chromium.org/183803022/ landing first. R=ulan@chromium.org Review URL: https://codereview.chromium.org/188063002 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19940 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/a64/deoptimizer-a64.cc | 6 +++ src/a64/frames-a64.cc | 8 ++++ src/arm/builtins-arm.cc | 10 ++++- src/arm/deoptimizer-arm.cc | 6 +++ src/deoptimizer.cc | 82 ++++++++++++++++++++++++------------ src/deoptimizer.h | 2 + src/frames-inl.h | 5 +++ src/frames.cc | 8 ++++ src/frames.h | 17 +++++++- src/ia32/deoptimizer-ia32.cc | 6 +++ src/x64/deoptimizer-x64.cc | 6 +++ 11 files changed, 125 insertions(+), 31 deletions(-) diff --git a/src/a64/deoptimizer-a64.cc b/src/a64/deoptimizer-a64.cc index 3fa1ddda8c..f3a5fcd4dd 100644 --- a/src/a64/deoptimizer-a64.cc +++ b/src/a64/deoptimizer-a64.cc @@ -377,6 +377,12 @@ void FrameDescription::SetCallerFp(unsigned offset, intptr_t value) { } +void FrameDescription::SetCallerConstantPool(unsigned offset, intptr_t value) { + // No out-of-line constant pool support. + UNREACHABLE(); +} + + #undef __ } } // namespace v8::internal diff --git a/src/a64/frames-a64.cc b/src/a64/frames-a64.cc index 56d2e26b72..ca5be3a585 100644 --- a/src/a64/frames-a64.cc +++ b/src/a64/frames-a64.cc @@ -40,10 +40,18 @@ namespace internal { Register JavaScriptFrame::fp_register() { return v8::internal::fp; } Register JavaScriptFrame::context_register() { return cp; } +Register JavaScriptFrame::constant_pool_pointer_register() { + UNREACHABLE(); + return no_reg; +} Register StubFailureTrampolineFrame::fp_register() { return v8::internal::fp; } Register StubFailureTrampolineFrame::context_register() { return cp; } +Register StubFailureTrampolineFrame::constant_pool_pointer_register() { + UNREACHABLE(); + return no_reg; +} Object*& ExitFrame::constant_pool_slot() const { diff --git a/src/arm/builtins-arm.cc b/src/arm/builtins-arm.cc index daca96d81a..f53f293cef 100644 --- a/src/arm/builtins-arm.cc +++ b/src/arm/builtins-arm.cc @@ -1353,8 +1353,14 @@ static void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) { // then tear down the parameters. __ ldr(r1, MemOperand(fp, -(StandardFrameConstants::kFixedFrameSizeFromFp + kPointerSize))); - __ mov(sp, fp); - __ ldm(ia_w, sp, fp.bit() | lr.bit()); + + if (FLAG_enable_ool_constant_pool) { + __ add(sp, fp, Operand(StandardFrameConstants::kConstantPoolOffset)); + __ ldm(ia_w, sp, pp.bit() | fp.bit() | lr.bit()); + } else { + __ mov(sp, fp);; + __ ldm(ia_w, sp, fp.bit() | lr.bit()); + } __ add(sp, sp, Operand::PointerOffsetFromSmiKey(r1)); __ add(sp, sp, Operand(kPointerSize)); // adjust for receiver } diff --git a/src/arm/deoptimizer-arm.cc b/src/arm/deoptimizer-arm.cc index 59e6e95900..ef3ea275cc 100644 --- a/src/arm/deoptimizer-arm.cc +++ b/src/arm/deoptimizer-arm.cc @@ -373,6 +373,12 @@ void FrameDescription::SetCallerFp(unsigned offset, intptr_t value) { } +void FrameDescription::SetCallerConstantPool(unsigned offset, intptr_t value) { + ASSERT(FLAG_enable_ool_constant_pool); + SetFrameSlot(offset, value); +} + + #undef __ } } // namespace v8::internal diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc index 8728a09501..9503f475eb 100644 --- a/src/deoptimizer.cc +++ b/src/deoptimizer.cc @@ -992,24 +992,19 @@ void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator, if (FLAG_enable_ool_constant_pool) { // For the bottommost output frame the constant pool pointer can be gotten - // from the input frame. For subsequent output frames, it can be gotten from - // the function's code. - Register constant_pool_reg = - JavaScriptFrame::constant_pool_pointer_register(); + // from the input frame. For subsequent output frames, it can be read from + // the previous frame. output_offset -= kPointerSize; input_offset -= kPointerSize; if (is_bottommost) { value = input_->GetFrameSlot(input_offset); } else { - value = reinterpret_cast( - function->shared()->code()->constant_pool()); + value = output_[frame_index - 1]->GetConstantPool(); } - output_frame->SetFrameSlot(output_offset, value); - output_frame->SetConstantPool(value); - if (is_topmost) output_frame->SetRegister(constant_pool_reg.code(), value); + output_frame->SetCallerConstantPool(output_offset, value); if (trace_scope_) { PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" - V8PRIxPTR "; constant_pool\n", + V8PRIxPTR "; caller's constant_pool\n", top_address + output_offset, output_offset, value); } } @@ -1067,6 +1062,18 @@ void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator, intptr_t pc_value = reinterpret_cast(start + pc_offset); output_frame->SetPc(pc_value); + // Update constant pool. + if (FLAG_enable_ool_constant_pool) { + intptr_t constant_pool_value = + reinterpret_cast(non_optimized_code->constant_pool()); + output_frame->SetConstantPool(constant_pool_value); + if (is_topmost) { + Register constant_pool_reg = + JavaScriptFrame::constant_pool_pointer_register(); + output_frame->SetRegister(constant_pool_reg.code(), constant_pool_value); + } + } + FullCodeGenerator::State state = FullCodeGenerator::StateField::decode(pc_and_state); output_frame->SetState(Smi::FromInt(state)); @@ -1150,15 +1157,14 @@ void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator, } if (FLAG_enable_ool_constant_pool) { - // A marker value is used in place of the constant pool. + // Read the caller's constant pool from the previous frame. output_offset -= kPointerSize; - intptr_t constant_pool = reinterpret_cast( - Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); - output_frame->SetFrameSlot(output_offset, constant_pool); + value = output_[frame_index - 1]->GetConstantPool(); + output_frame->SetCallerConstantPool(output_offset, value); if (trace_scope_) { PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" - V8PRIxPTR " ; constant_pool (adaptor sentinel)\n", - top_address + output_offset, output_offset, constant_pool); + V8PRIxPTR "; caller's constant_pool\n", + top_address + output_offset, output_offset, value); } } @@ -1205,6 +1211,11 @@ void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator, adaptor_trampoline->instruction_start() + isolate_->heap()->arguments_adaptor_deopt_pc_offset()->value()); output_frame->SetPc(pc_value); + if (FLAG_enable_ool_constant_pool) { + intptr_t constant_pool_value = + reinterpret_cast(adaptor_trampoline->constant_pool()); + output_frame->SetConstantPool(constant_pool_value); + } } @@ -1280,13 +1291,13 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator, } if (FLAG_enable_ool_constant_pool) { - // The constant pool pointer can be gotten from the previous frame. + // Read the caller's constant pool from the previous frame. output_offset -= kPointerSize; value = output_[frame_index - 1]->GetConstantPool(); - output_frame->SetFrameSlot(output_offset, value); + output_frame->SetCallerConstantPool(output_offset, value); if (trace_scope_) { PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" - V8PRIxPTR " ; constant pool\n", + V8PRIxPTR " ; caller's constant pool\n", top_address + output_offset, output_offset, value); } } @@ -1367,6 +1378,11 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator, construct_stub->instruction_start() + isolate_->heap()->construct_stub_deopt_pc_offset()->value()); output_frame->SetPc(pc); + if (FLAG_enable_ool_constant_pool) { + intptr_t constant_pool_value = + reinterpret_cast(construct_stub->constant_pool()); + output_frame->SetConstantPool(constant_pool_value); + } } @@ -1438,13 +1454,13 @@ void Deoptimizer::DoComputeAccessorStubFrame(TranslationIterator* iterator, } if (FLAG_enable_ool_constant_pool) { - // The constant pool pointer can be gotten from the previous frame. + // Read the caller's constant pool from the previous frame. output_offset -= kPointerSize; value = output_[frame_index - 1]->GetConstantPool(); - output_frame->SetFrameSlot(output_offset, value); + output_frame->SetCallerConstantPool(output_offset, value); if (trace_scope_) { PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" - V8PRIxPTR " ; constant pool\n", + V8PRIxPTR " ; caller's constant pool\n", top_address + output_offset, output_offset, value); } } @@ -1506,6 +1522,11 @@ void Deoptimizer::DoComputeAccessorStubFrame(TranslationIterator* iterator, intptr_t pc = reinterpret_cast( accessor_stub->instruction_start() + offset->value()); output_frame->SetPc(pc); + if (FLAG_enable_ool_constant_pool) { + intptr_t constant_pool_value = + reinterpret_cast(accessor_stub->constant_pool()); + output_frame->SetConstantPool(constant_pool_value); + } } @@ -1609,17 +1630,14 @@ void Deoptimizer::DoComputeCompiledStubFrame(TranslationIterator* iterator, } if (FLAG_enable_ool_constant_pool) { - // The constant pool pointer can be gotten from the input frame. - Register constant_pool_pointer_register = - StubFailureTrampolineFrame::constant_pool_pointer_register(); + // Read the caller's constant pool from the input frame. input_frame_offset -= kPointerSize; value = input_->GetFrameSlot(input_frame_offset); - output_frame->SetRegister(constant_pool_pointer_register.code(), value); output_frame_offset -= kPointerSize; - output_frame->SetFrameSlot(output_frame_offset, value); + output_frame->SetCallerConstantPool(output_frame_offset, value); if (trace_scope_) { PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" - V8PRIxPTR " ; constant_pool_pointer\n", + V8PRIxPTR " ; caller's constant_pool\n", top_address + output_frame_offset, output_frame_offset, value); } } @@ -1753,6 +1771,14 @@ void Deoptimizer::DoComputeCompiledStubFrame(TranslationIterator* iterator, ASSERT(trampoline != NULL); output_frame->SetPc(reinterpret_cast( trampoline->instruction_start())); + if (FLAG_enable_ool_constant_pool) { + Register constant_pool_reg = + StubFailureTrampolineFrame::constant_pool_pointer_register(); + intptr_t constant_pool_value = + reinterpret_cast(trampoline->constant_pool()); + output_frame->SetConstantPool(constant_pool_value); + output_frame->SetRegister(constant_pool_reg.code(), constant_pool_value); + } output_frame->SetState(Smi::FromInt(FullCodeGenerator::NO_REGISTERS)); Code* notify_failure = NotifyStubFailureBuiltin(); output_frame->SetContinuation( diff --git a/src/deoptimizer.h b/src/deoptimizer.h index 67690ded0d..71fb479064 100644 --- a/src/deoptimizer.h +++ b/src/deoptimizer.h @@ -508,6 +508,8 @@ class FrameDescription { void SetCallerFp(unsigned offset, intptr_t value); + void SetCallerConstantPool(unsigned offset, intptr_t value); + intptr_t GetRegister(unsigned n) const { #if DEBUG // This convoluted ASSERT is needed to work around a gcc problem that diff --git a/src/frames-inl.h b/src/frames-inl.h index 2973bad6af..e4dc91f95e 100644 --- a/src/frames-inl.h +++ b/src/frames-inl.h @@ -201,6 +201,11 @@ inline Address StandardFrame::ComputePCAddress(Address fp) { } +inline Address StandardFrame::ComputeConstantPoolAddress(Address fp) { + return fp + StandardFrameConstants::kConstantPoolOffset; +} + + inline bool StandardFrame::IsArgumentsAdaptorFrame(Address fp) { Object* marker = Memory::Object_at(fp + StandardFrameConstants::kContextOffset); diff --git a/src/frames.cc b/src/frames.cc index 3b55c276cf..0c47de910d 100644 --- a/src/frames.cc +++ b/src/frames.cc @@ -531,6 +531,10 @@ void ExitFrame::ComputeCallerState(State* state) const { state->fp = Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset); state->pc_address = ResolveReturnAddressLocation( reinterpret_cast(fp() + ExitFrameConstants::kCallerPCOffset)); + if (FLAG_enable_ool_constant_pool) { + state->constant_pool_address = reinterpret_cast( + fp() + ExitFrameConstants::kConstantPoolOffset); + } } @@ -574,6 +578,8 @@ void ExitFrame::FillState(Address fp, Address sp, State* state) { state->fp = fp; state->pc_address = ResolveReturnAddressLocation( reinterpret_cast(sp - 1 * kPCOnStackSize)); + state->constant_pool_address = + reinterpret_cast(fp + ExitFrameConstants::kConstantPoolOffset); } @@ -610,6 +616,8 @@ void StandardFrame::ComputeCallerState(State* state) const { state->fp = caller_fp(); state->pc_address = ResolveReturnAddressLocation( reinterpret_cast(ComputePCAddress(fp()))); + state->constant_pool_address = + reinterpret_cast(ComputeConstantPoolAddress(fp())); } diff --git a/src/frames.h b/src/frames.h index af2b55afb5..aef86bf61d 100644 --- a/src/frames.h +++ b/src/frames.h @@ -225,10 +225,12 @@ class StackFrame BASE_EMBEDDED { }; struct State { - State() : sp(NULL), fp(NULL), pc_address(NULL) { } + State() : sp(NULL), fp(NULL), pc_address(NULL), + constant_pool_address(NULL) { } Address sp; Address fp; Address* pc_address; + Address* constant_pool_address; }; // Copy constructor; it breaks the connection to host iterator @@ -270,6 +272,11 @@ class StackFrame BASE_EMBEDDED { Address pc() const { return *pc_address(); } void set_pc(Address pc) { *pc_address() = pc; } + Address constant_pool() const { return *constant_pool_address(); } + void set_constant_pool(ConstantPoolArray* constant_pool) { + *constant_pool_address() = reinterpret_cast
(constant_pool); + } + virtual void SetCallerFp(Address caller_fp) = 0; // Manually changes value of fp in this object. @@ -277,6 +284,10 @@ class StackFrame BASE_EMBEDDED { Address* pc_address() const { return state_.pc_address; } + Address* constant_pool_address() const { + return state_.constant_pool_address; + } + // Get the id of this stack frame. Id id() const { return static_cast(OffsetFrom(caller_sp())); } @@ -496,6 +507,10 @@ class StandardFrame: public StackFrame { // by the provided frame pointer. static inline Address ComputePCAddress(Address fp); + // Computes the address of the constant pool field in the standard + // frame given by the provided frame pointer. + static inline Address ComputeConstantPoolAddress(Address fp); + // Iterate over expression stack including stack handlers, locals, // and parts of the fixed part including context and code fields. void IterateExpressions(ObjectVisitor* v) const; diff --git a/src/ia32/deoptimizer-ia32.cc b/src/ia32/deoptimizer-ia32.cc index 546781eb87..711cdf86fb 100644 --- a/src/ia32/deoptimizer-ia32.cc +++ b/src/ia32/deoptimizer-ia32.cc @@ -463,6 +463,12 @@ void FrameDescription::SetCallerFp(unsigned offset, intptr_t value) { } +void FrameDescription::SetCallerConstantPool(unsigned offset, intptr_t value) { + // No out-of-line constant pool support. + UNREACHABLE(); +} + + #undef __ diff --git a/src/x64/deoptimizer-x64.cc b/src/x64/deoptimizer-x64.cc index 0b6791e59a..e35664a0ac 100644 --- a/src/x64/deoptimizer-x64.cc +++ b/src/x64/deoptimizer-x64.cc @@ -361,6 +361,12 @@ void FrameDescription::SetCallerFp(unsigned offset, intptr_t value) { } +void FrameDescription::SetCallerConstantPool(unsigned offset, intptr_t value) { + // No out-of-line constant pool support. + UNREACHABLE(); +} + + #undef __