diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc index 82c912efcf..204030f5be 100644 --- a/src/x64/lithium-codegen-x64.cc +++ b/src/x64/lithium-codegen-x64.cc @@ -297,10 +297,10 @@ void LCodeGen::GenerateBodyInstructionPost(LInstruction* instr) { bool LCodeGen::GenerateJumpTable() { + if (jump_table_.length() == 0) return !is_aborted(); + Label needs_frame; - if (jump_table_.length() > 0) { - Comment(";;; -------------------- Jump table --------------------"); - } + Comment(";;; -------------------- Jump table --------------------"); for (int i = 0; i < jump_table_.length(); i++) { Deoptimizer::JumpTableEntry* table_entry = &jump_table_[i]; __ bind(&table_entry->label); @@ -309,23 +309,7 @@ bool LCodeGen::GenerateJumpTable() { if (table_entry->needs_frame) { DCHECK(!info()->saves_caller_doubles()); __ Move(kScratchRegister, ExternalReference::ForDeoptEntry(entry)); - if (needs_frame.is_bound()) { - __ jmp(&needs_frame); - } else { - __ bind(&needs_frame); - __ movp(rsi, MemOperand(rbp, StandardFrameConstants::kContextOffset)); - __ pushq(rbp); - __ movp(rbp, rsp); - __ Push(rsi); - // This variant of deopt can only be used with stubs. Since we don't - // have a function pointer to install in the stack frame that we're - // building, install a special marker there instead. - DCHECK(info()->IsStub()); - __ Move(rsi, Smi::FromInt(StackFrame::STUB)); - __ Push(rsi); - __ movp(rsi, MemOperand(rsp, kPointerSize)); - __ call(kScratchRegister); - } + __ call(&needs_frame); } else { if (info()->saves_caller_doubles()) { DCHECK(info()->IsStub()); @@ -334,6 +318,55 @@ bool LCodeGen::GenerateJumpTable() { __ call(entry, RelocInfo::RUNTIME_ENTRY); } } + + if (needs_frame.is_linked()) { + __ bind(&needs_frame); + /* stack layout + 4: return address <-- rsp + 3: garbage + 2: garbage + 1: garbage + 0: garbage + */ + // Reserve space for context and stub marker. + __ subp(rsp, Immediate(2 * kPointerSize)); + __ Push(MemOperand(rsp, 2 * kPointerSize)); // Copy return address. + __ Push(kScratchRegister); // Save entry address for ret(0) + + /* stack layout + 4: return address + 3: garbage + 2: garbage + 1: return address + 0: entry address <-- rsp + */ + + // Remember context pointer. + __ movp(kScratchRegister, + MemOperand(rbp, StandardFrameConstants::kContextOffset)); + // Save context pointer into the stack frame. + __ movp(MemOperand(rsp, 3 * kPointerSize), kScratchRegister); + + // Create a stack frame. + __ movp(MemOperand(rsp, 4 * kPointerSize), rbp); + __ leap(rbp, MemOperand(rsp, 4 * kPointerSize)); + + // This variant of deopt can only be used with stubs. Since we don't + // have a function pointer to install in the stack frame that we're + // building, install a special marker there instead. + DCHECK(info()->IsStub()); + __ Move(MemOperand(rsp, 2 * kPointerSize), Smi::FromInt(StackFrame::STUB)); + + /* stack layout + 4: old ebp + 3: context pointer + 2: stub marker + 1: return address + 0: entry address <-- rsp + */ + __ ret(0); + } + return !is_aborted(); }