diff --git a/src/arm/builtins-arm.cc b/src/arm/builtins-arm.cc index 3be8e92849..00bc36797a 100644 --- a/src/arm/builtins-arm.cc +++ b/src/arm/builtins-arm.cc @@ -1272,10 +1272,8 @@ void Builtins::Generate_NotifyStubFailure(MacroAssembler* masm) { __ ldm(ia_w, sp, kJSCallerSaved | kCalleeSaved); } - __ mov(ip, lr); // Stash the miss continuation __ add(sp, sp, Operand(kPointerSize)); // Ignore state - __ pop(lr); // Restore LR to continuation in JSFunction - __ mov(pc, ip); // Jump to miss handler + __ mov(pc, lr); // Jump to miss handler } diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc index 8889e756f6..d0b4d1eb10 100644 --- a/src/arm/code-stubs-arm.cc +++ b/src/arm/code-stubs-arm.cc @@ -7862,6 +7862,16 @@ void StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) { } +void StubFailureTrampolineStub::Generate(MacroAssembler* masm) { + ASSERT(!Serializer::enabled()); + bool save_fp_regs = CpuFeatures::IsSupported(VFP2); + CEntryStub ces(1, save_fp_regs ? kSaveFPRegs : kDontSaveFPRegs); + __ Call(ces.GetCode(), RelocInfo::CODE_TARGET); + masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); + __ Ret(); +} + + void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { if (entry_hook_ != NULL) { PredictableCodeSizeScope predictable(masm, 4 * Assembler::kInstrSize); diff --git a/src/arm/deoptimizer-arm.cc b/src/arm/deoptimizer-arm.cc index ab35281d36..a822a8e239 100644 --- a/src/arm/deoptimizer-arm.cc +++ b/src/arm/deoptimizer-arm.cc @@ -455,22 +455,27 @@ void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator, void Deoptimizer::DoCompiledStubFrame(TranslationIterator* iterator, int frame_index) { // - // FROM TO <-fp + // FROM TO // | .... | | .... | // +-------------------------+ +-------------------------+ - // | JSFunction continuation | | parameter 1 | + // | JSFunction continuation | | JSFunction continuation | // +-------------------------+ +-------------------------+ - // | | saved frame (fp) | | .... | - // | +=========================+<-fp +-------------------------+ - // | | JSFunction context | | parameter n | + // | | saved frame (fp) | | saved frame (fp) | + // | +=========================+<-fp +=========================+<-fp + // | | JSFunction context | | JSFunction context | // v +-------------------------+ +-------------------------| - // | COMPILED_STUB marker | | JSFunction continuation | - // +-------------------------+ +-------------------------+<-sp - // | | r0 = number of parameters - // | ... | r1 = failure handler address - // | | fp = saved frame - // +-------------------------+<-sp cp = JSFunction context - // + // | COMPILED_STUB marker | | STUB_FAILURE marker | + // +-------------------------+ +-------------------------+ + // | | | stub parameter 1 | + // | ... | +-------------------------+ + // | | | ... | + // |-------------------------|<-sp +-------------------------+ + // | stub parameter n | + // parameters in registers +-------------------------+<-sp + // and spilled to stack r0 = number of parameters + // r1 = failure handler address + // fp = saved frame + // cp = JSFunction context // ASSERT(compiled_code_->kind() == Code::COMPILED_STUB); @@ -478,48 +483,65 @@ void Deoptimizer::DoCompiledStubFrame(TranslationIterator* iterator, CodeStubInterfaceDescriptor* descriptor = isolate_->code_stub_interface_descriptor(major_key); - int output_frame_size = - (1 + descriptor->register_param_count_) * kPointerSize; + int output_frame_size = StandardFrameConstants::kFixedFrameSize + + kPointerSize * descriptor->register_param_count_; + FrameDescription* output_frame = new(output_frame_size) FrameDescription(output_frame_size, 0); + ASSERT(frame_index == 0); + output_[frame_index] = output_frame; Code* notify_failure = isolate_->builtins()->builtin(Builtins::kNotifyStubFailure); output_frame->SetState(Smi::FromInt(FullCodeGenerator::NO_REGISTERS)); output_frame->SetContinuation( - reinterpret_cast(notify_failure->entry())); + reinterpret_cast(notify_failure->entry())); - Code* code; - CEntryStub(1, kSaveFPRegs).FindCodeInCache(&code, isolate_); - output_frame->SetPc(reinterpret_cast(code->instruction_start())); + Code* trampoline = NULL; + StubFailureTrampolineStub().FindCodeInCache(&trampoline, isolate_); + ASSERT(trampoline != NULL); + output_frame->SetPc(reinterpret_cast( + trampoline->instruction_start())); unsigned input_frame_size = input_->GetFrameSize(); - intptr_t value = input_->GetFrameSlot(input_frame_size - kPointerSize); - output_frame->SetFrameSlot(0, value); - value = input_->GetFrameSlot(input_frame_size - 2 * kPointerSize); + + // JSFunction continuation + intptr_t input_frame_offset = input_frame_size - kPointerSize; + intptr_t output_frame_offset = output_frame_size - kPointerSize; + intptr_t value = input_->GetFrameSlot(input_frame_offset); + output_frame->SetFrameSlot(output_frame_offset, value); + + // saved frame ptr + input_frame_offset -= kPointerSize; + value = input_->GetFrameSlot(input_frame_offset); + output_frame_offset -= kPointerSize; + output_frame->SetFrameSlot(output_frame_offset, value); + + // Restore context + input_frame_offset -= kPointerSize; + value = input_->GetFrameSlot(input_frame_offset); + output_frame->SetRegister(cp.code(), value); + output_frame_offset -= kPointerSize; + output_frame->SetFrameSlot(output_frame_offset, value); + + // Internal frame markers + output_frame_offset -= kPointerSize; + value = reinterpret_cast( + Smi::FromInt(StackFrame::STUB_FAILURE_TRAMPOLINE)); + output_frame->SetFrameSlot(output_frame_offset, value); + + for (int i = 0; i < descriptor->register_param_count_; ++i) { + output_frame_offset -= kPointerSize; + DoTranslateCommand(iterator, 0, output_frame_offset); + } + + value = input_->GetRegister(fp.code()); output_frame->SetRegister(fp.code(), value); output_frame->SetFp(value); - value = input_->GetFrameSlot(input_frame_size - 3 * kPointerSize); - output_frame->SetRegister(cp.code(), value); - - int parameter_offset = kPointerSize * descriptor->register_param_count_; - for (int i = 0; i < descriptor->register_param_count_; ++i) { - Translation::Opcode opcode = - static_cast(iterator->Next()); - ASSERT(opcode == Translation::REGISTER); - USE(opcode); - int input_reg = iterator->Next(); - intptr_t reg_value = input_->GetRegister(input_reg); - output_frame->SetFrameSlot(parameter_offset, reg_value); - parameter_offset -= kPointerSize; - } ApiFunction function(descriptor->deoptimization_handler_); ExternalReference xref(&function, ExternalReference::BUILTIN_CALL, isolate_); intptr_t handler = reinterpret_cast(xref.address()); output_frame->SetRegister(r0.code(), descriptor->register_param_count_); output_frame->SetRegister(r1.code(), handler); - - ASSERT(frame_index == 0); - output_[frame_index] = output_frame; } diff --git a/src/code-stubs.h b/src/code-stubs.h index 96c208980f..bd572c2f26 100644 --- a/src/code-stubs.h +++ b/src/code-stubs.h @@ -78,6 +78,7 @@ namespace internal { V(StringDictionaryLookup) \ V(ElementsTransitionAndStore) \ V(StoreArrayLiteralElement) \ + V(StubFailureTrampoline) \ V(ProfileEntryHook) // List of code stubs only used on ARM platforms. @@ -1382,6 +1383,20 @@ class StoreArrayLiteralElementStub : public PlatformCodeStub { }; +class StubFailureTrampolineStub : public PlatformCodeStub { + public: + StubFailureTrampolineStub() {} + + private: + Major MajorKey() { return StubFailureTrampoline; } + int MinorKey() { return 0; } + + void Generate(MacroAssembler* masm); + + DISALLOW_COPY_AND_ASSIGN(StubFailureTrampolineStub); +}; + + class ProfileEntryHookStub : public PlatformCodeStub { public: explicit ProfileEntryHookStub() {} diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc index b10fb744cf..8015baf6e9 100644 --- a/src/deoptimizer.cc +++ b/src/deoptimizer.cc @@ -554,7 +554,10 @@ Deoptimizer::Deoptimizer(Isolate* isolate, ASSERT(HEAP->allow_allocation(false)); unsigned size = ComputeInputFrameSize(); input_ = new(size) FrameDescription(size, function); - input_->SetFrameType(StackFrame::JAVA_SCRIPT); + StackFrame::Type frame_type = function == NULL + ? StackFrame::STUB + : StackFrame::JAVA_SCRIPT; + input_->SetFrameType(frame_type); } @@ -1664,6 +1667,8 @@ int FrameDescription::ComputeParametersCount() { // Can't use GetExpression(0) because it would cause infinite recursion. return reinterpret_cast(*GetFrameSlotPointer(0))->value(); } + case StackFrame::STUB: + return 0; default: UNREACHABLE(); return 0; diff --git a/src/frames-inl.h b/src/frames-inl.h index a514632cbe..e0c934f46c 100644 --- a/src/frames-inl.h +++ b/src/frames-inl.h @@ -255,6 +255,11 @@ inline InternalFrame::InternalFrame(StackFrameIterator* iterator) } +inline StubFailureTrampolineFrame::StubFailureTrampolineFrame( + StackFrameIterator* iterator) : InternalFrame(iterator) { +} + + inline ConstructFrame::ConstructFrame(StackFrameIterator* iterator) : InternalFrame(iterator) { } diff --git a/src/frames.cc b/src/frames.cc index 7f0a48dc6c..98b3d65f95 100644 --- a/src/frames.cc +++ b/src/frames.cc @@ -1303,6 +1303,15 @@ void InternalFrame::Iterate(ObjectVisitor* v) const { } +void StubFailureTrampolineFrame::Iterate(ObjectVisitor* v) const { + const int offset = StandardFrameConstants::kContextOffset; + Object** base = &Memory::Object_at(sp()); + Object** limit = &Memory::Object_at(fp() + offset) + 1; + v->VisitPointers(base, limit); + IteratePc(v, pc_address(), LookupCode()); +} + + // ------------------------------------------------------------------------- diff --git a/src/frames.h b/src/frames.h index a1d24ac3a0..26bf434ac9 100644 --- a/src/frames.h +++ b/src/frames.h @@ -130,16 +130,17 @@ class StackHandler BASE_EMBEDDED { }; -#define STACK_FRAME_TYPE_LIST(V) \ - V(ENTRY, EntryFrame) \ - V(ENTRY_CONSTRUCT, EntryConstructFrame) \ - V(EXIT, ExitFrame) \ - V(JAVA_SCRIPT, JavaScriptFrame) \ - V(OPTIMIZED, OptimizedFrame) \ - V(STUB, StubFrame) \ - V(INTERNAL, InternalFrame) \ - V(CONSTRUCT, ConstructFrame) \ - V(ARGUMENTS_ADAPTOR, ArgumentsAdaptorFrame) +#define STACK_FRAME_TYPE_LIST(V) \ + V(ENTRY, EntryFrame) \ + V(ENTRY_CONSTRUCT, EntryConstructFrame) \ + V(EXIT, ExitFrame) \ + V(JAVA_SCRIPT, JavaScriptFrame) \ + V(OPTIMIZED, OptimizedFrame) \ + V(STUB, StubFrame) \ + V(STUB_FAILURE_TRAMPOLINE, StubFailureTrampolineFrame) \ + V(INTERNAL, InternalFrame) \ + V(CONSTRUCT, ConstructFrame) \ + V(ARGUMENTS_ADAPTOR, ArgumentsAdaptorFrame) // Abstract base class for all stack frames. @@ -194,6 +195,9 @@ class StackFrame BASE_EMBEDDED { bool is_optimized() const { return type() == OPTIMIZED; } bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; } bool is_internal() const { return type() == INTERNAL; } + bool is_stub_failure_trampoline() const { + return type() == STUB_FAILURE_TRAMPOLINE; + } bool is_construct() const { return type() == CONSTRUCT; } virtual bool is_standard() const { return false; } @@ -668,6 +672,21 @@ class InternalFrame: public StandardFrame { }; +class StubFailureTrampolineFrame: public InternalFrame { + public: + virtual Type type() const { return STUB_FAILURE_TRAMPOLINE; } + + virtual void Iterate(ObjectVisitor* v) const; + + protected: + inline explicit StubFailureTrampolineFrame( + StackFrameIterator* iterator); + + private: + friend class StackFrameIterator; +}; + + // Construct frames are special trampoline frames introduced to handle // function invocations through 'new'. class ConstructFrame: public InternalFrame { diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc index 35bda31f90..25ff1d5039 100644 --- a/src/ia32/code-stubs-ia32.cc +++ b/src/ia32/code-stubs-ia32.cc @@ -7629,6 +7629,16 @@ void StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) { } +void StubFailureTrampolineStub::Generate(MacroAssembler* masm) { + ASSERT(!Serializer::enabled()); + bool save_fp_regs = CpuFeatures::IsSupported(SSE2); + CEntryStub ces(1, save_fp_regs ? kSaveFPRegs : kDontSaveFPRegs); + __ call(ces.GetCode(), RelocInfo::CODE_TARGET); + masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); + __ ret(0); // Return to IC Miss stub, continuation still on stack. +} + + void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { if (entry_hook_ != NULL) { ProfileEntryHookStub stub; diff --git a/src/ia32/deoptimizer-ia32.cc b/src/ia32/deoptimizer-ia32.cc index 029dbfbe29..8da0739b96 100644 --- a/src/ia32/deoptimizer-ia32.cc +++ b/src/ia32/deoptimizer-ia32.cc @@ -562,22 +562,27 @@ void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator, void Deoptimizer::DoCompiledStubFrame(TranslationIterator* iterator, int frame_index) { // - // FROM TO <-ebp + // FROM TO // | .... | | .... | // +-------------------------+ +-------------------------+ - // | JSFunction continuation | | parameter 1 | + // | JSFunction continuation | | JSFunction continuation | // +-------------------------+ +-------------------------+ - // | | saved frame (ebp) | | .... | - // | +=========================+<-ebp +-------------------------+ - // | | JSFunction context | | parameter n | + // | | saved frame (ebp) | | saved frame (ebp) | + // | +=========================+<-ebp +=========================+<-ebp + // | | JSFunction context | | JSFunction context | // v +-------------------------+ +-------------------------| - // | COMPILED_STUB marker | | JSFunction continuation | - // +-------------------------+ +-------------------------+<-esp - // | | eax = number of parameters - // | ... | ebx = failure handler address - // | | ebp = saved frame - // +-------------------------+<-esp esi = JSFunction context - // + // | COMPILED_STUB marker | | STUB_FAILURE marker | + // +-------------------------+ +-------------------------+ + // | | | stub parameter 1 | + // | ... | +-------------------------+ + // | | | ... | + // |-------------------------|<-esp +-------------------------+ + // | stub parameter n | + // parameters in registers +-------------------------+<-esp + // and spilled to stack eax = number of parameters + // ebx = failure handler address + // ebp = saved frame + // esi = JSFunction context // ASSERT(compiled_code_->kind() == Code::COMPILED_STUB); @@ -585,49 +590,64 @@ void Deoptimizer::DoCompiledStubFrame(TranslationIterator* iterator, CodeStubInterfaceDescriptor* descriptor = isolate_->code_stub_interface_descriptor(major_key); - int output_frame_size = - (1 + descriptor->register_param_count_) * kPointerSize; + int output_frame_size = StandardFrameConstants::kFixedFrameSize + + kPointerSize * descriptor->register_param_count_; + FrameDescription* output_frame = new(output_frame_size) FrameDescription(output_frame_size, 0); + ASSERT(frame_index == 0); + output_[frame_index] = output_frame; Code* notify_failure = isolate_->builtins()->builtin(Builtins::kNotifyStubFailure); output_frame->SetState(Smi::FromInt(FullCodeGenerator::NO_REGISTERS)); output_frame->SetContinuation( - reinterpret_cast(notify_failure->entry())); + reinterpret_cast(notify_failure->entry())); - Code* code; - SaveFPRegsMode mode = - CpuFeatures::IsSupported(SSE2) ? kSaveFPRegs : kDontSaveFPRegs; - CEntryStub(1, mode).FindCodeInCache(&code, isolate_); - output_frame->SetPc(reinterpret_cast(code->instruction_start())); + Code* trampoline = NULL; + StubFailureTrampolineStub().FindCodeInCache(&trampoline, isolate_); + ASSERT(trampoline != NULL); + output_frame->SetPc(reinterpret_cast( + trampoline->instruction_start())); unsigned input_frame_size = input_->GetFrameSize(); - intptr_t value = input_->GetFrameSlot(input_frame_size - kPointerSize); - output_frame->SetFrameSlot(0, value); - value = input_->GetFrameSlot(input_frame_size - 2 * kPointerSize); + + // JSFunction continuation + intptr_t input_frame_offset = input_frame_size - kPointerSize; + intptr_t output_frame_offset = output_frame_size - kPointerSize; + intptr_t value = input_->GetFrameSlot(input_frame_offset); + output_frame->SetFrameSlot(output_frame_offset, value); + + // saved frame ptr + input_frame_offset -= kPointerSize; + value = input_->GetFrameSlot(input_frame_offset); + output_frame_offset -= kPointerSize; + output_frame->SetFrameSlot(output_frame_offset, value); + + // Restore context + input_frame_offset -= kPointerSize; + value = input_->GetFrameSlot(input_frame_offset); + output_frame->SetRegister(esi.code(), value); + output_frame_offset -= kPointerSize; + output_frame->SetFrameSlot(output_frame_offset, value); + + // Internal frame markers + output_frame_offset -= kPointerSize; + value = reinterpret_cast( + Smi::FromInt(StackFrame::STUB_FAILURE_TRAMPOLINE)); + output_frame->SetFrameSlot(output_frame_offset, value); + + for (int i = 0; i < descriptor->register_param_count_; ++i) { + output_frame_offset -= kPointerSize; + DoTranslateCommand(iterator, 0, output_frame_offset); + } + + value = input_->GetRegister(ebp.code()); output_frame->SetRegister(ebp.code(), value); output_frame->SetFp(value); - value = input_->GetFrameSlot(input_frame_size - 3 * kPointerSize); - output_frame->SetRegister(esi.code(), value); - - int parameter_offset = kPointerSize * descriptor->register_param_count_; - for (int i = 0; i < descriptor->register_param_count_; ++i) { - Translation::Opcode opcode = - static_cast(iterator->Next()); - ASSERT(opcode == Translation::REGISTER); - USE(opcode); - int input_reg = iterator->Next(); - intptr_t reg_value = input_->GetRegister(input_reg); - output_frame->SetFrameSlot(parameter_offset, reg_value); - parameter_offset -= kPointerSize; - } intptr_t handler = reinterpret_cast(descriptor->deoptimization_handler_); output_frame->SetRegister(eax.code(), descriptor->register_param_count_); output_frame->SetRegister(ebx.code(), handler); - - ASSERT(frame_index == 0); - output_[frame_index] = output_frame; } diff --git a/src/ic.cc b/src/ic.cc index c452791e75..23a5a7e340 100644 --- a/src/ic.cc +++ b/src/ic.cc @@ -112,30 +112,15 @@ void IC::TraceIC(const char* type, IC::IC(FrameDepth depth, Isolate* isolate) : isolate_(isolate) { ASSERT(isolate == Isolate::Current()); - // To improve the performance of the (much used) IC code, we unfold - // a few levels of the stack frame iteration code. This yields a - // ~35% speedup when running DeltaBlue with the '--nouse-ic' flag. - const Address entry = - Isolate::c_entry_fp(isolate->thread_local_top()); - Address* pc_address = - reinterpret_cast(entry + ExitFrameConstants::kCallerPCOffset); - Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset); - // If there's another JavaScript frame on the stack, we need to look - // one frame further down the stack to find the frame pointer and - // the return address stack slot. - if (depth == EXTRA_CALL_FRAME) { - const int kCallerPCOffset = StandardFrameConstants::kCallerPCOffset; - pc_address = reinterpret_cast(fp + kCallerPCOffset); - fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset); - } -#ifdef DEBUG StackFrameIterator it; for (int i = 0; i < depth + 1; i++) it.Advance(); + // Skip StubFailureTrampolineFrames + if (it.frame()->is_stub_failure_trampoline()) { + it.Advance(); + } StackFrame* frame = it.frame(); - ASSERT(fp == frame->fp() && pc_address == frame->pc_address()); -#endif - fp_ = fp; - pc_address_ = pc_address; + fp_ = frame->fp(); + pc_address_ = frame->pc_address(); } diff --git a/src/isolate.cc b/src/isolate.cc index 0e59578d0a..2774cc9210 100644 --- a/src/isolate.cc +++ b/src/isolate.cc @@ -2093,6 +2093,9 @@ bool Isolate::Init(Deserializer* des) { Deoptimizer::EnsureCodeForDeoptimizationEntry( Deoptimizer::LAZY, kDeoptTableSerializeEntryCount - 1); + + // Ensure that the stub failure trampoline has been generated. + StubFailureTrampolineStub().GetCode(); } if (FLAG_parallel_recompilation) optimizing_compiler_thread_.Start(); diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc index a0424acd03..109fcfcd40 100644 --- a/src/x64/code-stubs-x64.cc +++ b/src/x64/code-stubs-x64.cc @@ -6619,6 +6619,15 @@ void StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) { } +void StubFailureTrampolineStub::Generate(MacroAssembler* masm) { + ASSERT(!Serializer::enabled()); + CEntryStub ces(1, kSaveFPRegs); + __ Call(ces.GetCode(), RelocInfo::CODE_TARGET); + masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); + __ ret(0); // Return to IC Miss stub, continuation still on stack. +} + + void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { if (entry_hook_ != NULL) { ProfileEntryHookStub stub; diff --git a/src/x64/deoptimizer-x64.cc b/src/x64/deoptimizer-x64.cc index 79c8cd119d..7d78765d62 100644 --- a/src/x64/deoptimizer-x64.cc +++ b/src/x64/deoptimizer-x64.cc @@ -451,22 +451,27 @@ void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator, void Deoptimizer::DoCompiledStubFrame(TranslationIterator* iterator, int frame_index) { // - // FROM TO <-rbp + // FROM TO // | .... | | .... | // +-------------------------+ +-------------------------+ - // | JSFunction continuation | | parameter 1 | + // | JSFunction continuation | | JSFunction continuation | // +-------------------------+ +-------------------------+ - // | | saved frame (rbp) | | .... | - // | +=========================+<-rbp +-------------------------+ - // | | JSFunction context | | parameter n | + // | | saved frame (rbp) | | saved frame (rbp) | + // | +=========================+<-rbp +=========================+<-rbp + // | | JSFunction context | | JSFunction context | // v +-------------------------+ +-------------------------| - // | COMPILED_STUB marker | | JSFunction continuation | - // +-------------------------+ +-------------------------+<-rsp - // | | rax = number of parameters - // | ... | rbx = failure handler address - // | | rbp = saved frame - // +-------------------------+<-rsp rsi = JSFunction context - // + // | COMPILED_STUB marker | | STUB_FAILURE marker | + // +-------------------------+ +-------------------------+ + // | | | stub parameter 1 | + // | ... | +-------------------------+ + // | | | ... | + // |-------------------------|<-rsp +-------------------------+ + // | stub parameter n | + // parameters in registers +-------------------------+<-rsp + // and spilled to stack rax = number of parameters + // rbx = failure handler address + // rbp = saved frame + // rsi = JSFunction context // ASSERT(compiled_code_->kind() == Code::COMPILED_STUB); @@ -474,47 +479,64 @@ void Deoptimizer::DoCompiledStubFrame(TranslationIterator* iterator, CodeStubInterfaceDescriptor* descriptor = isolate_->code_stub_interface_descriptor(major_key); - int output_frame_size = - (1 + descriptor->register_param_count_) * kPointerSize; + int output_frame_size = StandardFrameConstants::kFixedFrameSize + + kPointerSize * descriptor->register_param_count_; + FrameDescription* output_frame = new(output_frame_size) FrameDescription(output_frame_size, 0); + ASSERT(frame_index == 0); + output_[frame_index] = output_frame; Code* notify_failure = isolate_->builtins()->builtin(Builtins::kNotifyStubFailure); output_frame->SetState(Smi::FromInt(FullCodeGenerator::NO_REGISTERS)); output_frame->SetContinuation( reinterpret_cast(notify_failure->entry())); - Code* code; - CEntryStub(1, kDontSaveFPRegs).FindCodeInCache(&code, isolate_); - output_frame->SetPc(reinterpret_cast(code->instruction_start())); + Code* trampoline = NULL; + StubFailureTrampolineStub().FindCodeInCache(&trampoline, isolate_); + ASSERT(trampoline != NULL); + output_frame->SetPc(reinterpret_cast( + trampoline->instruction_start())); unsigned input_frame_size = input_->GetFrameSize(); - intptr_t value = input_->GetFrameSlot(input_frame_size - kPointerSize); - output_frame->SetFrameSlot(0, value); - value = input_->GetFrameSlot(input_frame_size - 2 * kPointerSize); + + // JSFunction continuation + intptr_t input_frame_offset = input_frame_size - kPointerSize; + intptr_t output_frame_offset = output_frame_size - kPointerSize; + intptr_t value = input_->GetFrameSlot(input_frame_offset); + output_frame->SetFrameSlot(output_frame_offset, value); + + // saved frame ptr + input_frame_offset -= kPointerSize; + value = input_->GetFrameSlot(input_frame_offset); + output_frame_offset -= kPointerSize; + output_frame->SetFrameSlot(output_frame_offset, value); + + // Restore context + input_frame_offset -= kPointerSize; + value = input_->GetFrameSlot(input_frame_offset); + output_frame->SetRegister(rsi.code(), value); + output_frame_offset -= kPointerSize; + output_frame->SetFrameSlot(output_frame_offset, value); + + // Internal frame markers + output_frame_offset -= kPointerSize; + value = reinterpret_cast( + Smi::FromInt(StackFrame::STUB_FAILURE_TRAMPOLINE)); + output_frame->SetFrameSlot(output_frame_offset, value); + + for (int i = 0; i < descriptor->register_param_count_; ++i) { + output_frame_offset -= kPointerSize; + DoTranslateCommand(iterator, 0, output_frame_offset); + } + + value = input_->GetRegister(rbp.code()); output_frame->SetRegister(rbp.code(), value); output_frame->SetFp(value); - value = input_->GetFrameSlot(input_frame_size - 3 * kPointerSize); - output_frame->SetRegister(rsi.code(), value); - - int parameter_offset = kPointerSize * descriptor->register_param_count_; - for (int i = 0; i < descriptor->register_param_count_; ++i) { - Translation::Opcode opcode = - static_cast(iterator->Next()); - ASSERT(opcode == Translation::REGISTER); - USE(opcode); - int input_reg = iterator->Next(); - intptr_t reg_value = input_->GetRegister(input_reg); - output_frame->SetFrameSlot(parameter_offset, reg_value); - parameter_offset -= kPointerSize; - } intptr_t handler = reinterpret_cast(descriptor->deoptimization_handler_); output_frame->SetRegister(rax.code(), descriptor->register_param_count_); output_frame->SetRegister(rbx.code(), handler); - - ASSERT(frame_index == 0); - output_[frame_index] = output_frame; }