diff --git a/src/builtins/x64/builtins-x64.cc b/src/builtins/x64/builtins-x64.cc index 5a493d9b64..986d1e435b 100644 --- a/src/builtins/x64/builtins-x64.cc +++ b/src/builtins/x64/builtins-x64.cc @@ -45,8 +45,9 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm, Address address) { RelocInfo::CODE_TARGET); } -static void GenerateTailCallToReturnedCode(MacroAssembler* masm, - Runtime::FunctionId function_id) { +static void GenerateTailCallToReturnedCode( + MacroAssembler* masm, Runtime::FunctionId function_id, + JumpMode jump_mode = JumpMode::kJump) { // ----------- S t a t e ------------- // -- rax : actual argument count // -- rdx : new target (preserved for callee) @@ -73,7 +74,7 @@ static void GenerateTailCallToReturnedCode(MacroAssembler* masm, __ Pop(kJavaScriptCallTargetRegister); } static_assert(kJavaScriptCallCodeStartRegister == rcx, "ABI mismatch"); - __ JumpCodeObject(rcx); + __ JumpCodeObject(rcx, jump_mode); } namespace { @@ -917,7 +918,8 @@ static void MaybeOptimizeCode(MacroAssembler* masm, Register feedback_vector, static void TailCallOptimizedCodeSlot(MacroAssembler* masm, Register optimized_code_entry, - Register scratch1, Register scratch2) { + Register scratch1, Register scratch2, + JumpMode jump_mode) { // ----------- S t a t e ------------- // -- rax : actual argument count // -- rdx : new target (preserved for callee if needed, and caller) @@ -947,13 +949,14 @@ static void TailCallOptimizedCodeSlot(MacroAssembler* masm, scratch1, scratch2); static_assert(kJavaScriptCallCodeStartRegister == rcx, "ABI mismatch"); __ Move(rcx, optimized_code_entry); - __ JumpCodeObject(rcx); + __ JumpCodeObject(rcx, jump_mode); // Optimized code slot contains deoptimized code or code is cleared and // optimized code marker isn't updated. Evict the code, update the marker // and re-enter the closure's code. __ bind(&heal_optimized_code_slot); - GenerateTailCallToReturnedCode(masm, Runtime::kHealOptimizedCodeSlot); + GenerateTailCallToReturnedCode(masm, Runtime::kHealOptimizedCodeSlot, + jump_mode); } // Advance the current bytecode offset. This simulates what all bytecode @@ -1039,8 +1042,8 @@ static void AdvanceBytecodeOffsetOrReturn(MacroAssembler* masm, } static void MaybeOptimizeCodeOrTailCallOptimizedCodeSlot( - MacroAssembler* masm, Register optimization_state, - Register feedback_vector) { + MacroAssembler* masm, Register optimization_state, Register feedback_vector, + JumpMode jump_mode = JumpMode::kJump) { Label maybe_has_optimized_code; __ testl( optimization_state, @@ -1056,7 +1059,7 @@ static void MaybeOptimizeCodeOrTailCallOptimizedCodeSlot( __ LoadAnyTaggedField( optimized_code_entry, FieldOperand(feedback_vector, FeedbackVector::kMaybeOptimizedCodeOffset)); - TailCallOptimizedCodeSlot(masm, optimized_code_entry, r11, r15); + TailCallOptimizedCodeSlot(masm, optimized_code_entry, r11, r15, jump_mode); } // Generate code for entering a JS function with the interpreter. @@ -1717,10 +1720,13 @@ void Builtins::Generate_BaselineOutOfLinePrologue(MacroAssembler* masm) { __ bind(&has_optimized_code_or_marker); { __ RecordComment("[ Optimized marker check"); - // TODO(v8:11429,verwaest): Overwrite return address instead. - // Drop the return adress + // Drop the return address, rebalancing the return stack buffer by using + // JumpMode::kPushAndReturn. We can't leave the slot and overwrite it on + // return since we may do a runtime call along the way that requires the + // stack to only contain valid frames. __ Drop(1); - MaybeOptimizeCodeOrTailCallOptimizedCodeSlot(masm, rcx, feedback_vector); + MaybeOptimizeCodeOrTailCallOptimizedCodeSlot(masm, rcx, feedback_vector, + JumpMode::kPushAndReturn); __ Trap(); __ RecordComment("]"); } @@ -1829,7 +1835,8 @@ void Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) { void Builtins::Generate_TailCallOptimizedCodeSlot(MacroAssembler* masm) { Register optimized_code_entry = kJavaScriptCallCodeStartRegister; - TailCallOptimizedCodeSlot(masm, optimized_code_entry, r11, r15); + TailCallOptimizedCodeSlot(masm, optimized_code_entry, r11, r15, + JumpMode::kJump); } // static diff --git a/src/codegen/arm/macro-assembler-arm.cc b/src/codegen/arm/macro-assembler-arm.cc index 3c13ba494b..fd9533f7ec 100644 --- a/src/codegen/arm/macro-assembler-arm.cc +++ b/src/codegen/arm/macro-assembler-arm.cc @@ -366,7 +366,8 @@ void TurboAssembler::CallCodeObject(Register code_object) { Call(code_object); } -void TurboAssembler::JumpCodeObject(Register code_object) { +void TurboAssembler::JumpCodeObject(Register code_object, JumpMode jump_mode) { + DCHECK_EQ(JumpMode::kJump, jump_mode); LoadCodeObjectEntry(code_object, code_object); Jump(code_object); } diff --git a/src/codegen/arm/macro-assembler-arm.h b/src/codegen/arm/macro-assembler-arm.h index 9cef2cd641..2f7863b54c 100644 --- a/src/codegen/arm/macro-assembler-arm.h +++ b/src/codegen/arm/macro-assembler-arm.h @@ -317,7 +317,8 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase { void LoadCodeObjectEntry(Register destination, Register code_object) override; void CallCodeObject(Register code_object) override; - void JumpCodeObject(Register code_object) override; + void JumpCodeObject(Register code_object, + JumpMode jump_mode = JumpMode::kJump) override; // Generates an instruction sequence s.t. the return address points to the // instruction following the call. diff --git a/src/codegen/arm64/macro-assembler-arm64.cc b/src/codegen/arm64/macro-assembler-arm64.cc index d110f0781d..54a9e0be5d 100644 --- a/src/codegen/arm64/macro-assembler-arm64.cc +++ b/src/codegen/arm64/macro-assembler-arm64.cc @@ -1982,7 +1982,8 @@ void TurboAssembler::CallCodeObject(Register code_object) { Call(code_object); } -void TurboAssembler::JumpCodeObject(Register code_object) { +void TurboAssembler::JumpCodeObject(Register code_object, JumpMode jump_mode) { + DCHECK_EQ(JumpMode::kJump, jump_mode); LoadCodeObjectEntry(code_object, code_object); UseScratchRegisterScope temps(this); diff --git a/src/codegen/arm64/macro-assembler-arm64.h b/src/codegen/arm64/macro-assembler-arm64.h index 7ef2946e9c..ef7bc15166 100644 --- a/src/codegen/arm64/macro-assembler-arm64.h +++ b/src/codegen/arm64/macro-assembler-arm64.h @@ -979,7 +979,8 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase { void LoadCodeObjectEntry(Register destination, Register code_object) override; void CallCodeObject(Register code_object) override; - void JumpCodeObject(Register code_object) override; + void JumpCodeObject(Register code_object, + JumpMode jump_mode = JumpMode::kJump) override; // Generates an instruction sequence s.t. the return address points to the // instruction following the call. diff --git a/src/codegen/ia32/macro-assembler-ia32.cc b/src/codegen/ia32/macro-assembler-ia32.cc index 6a30d5c558..c58999e6d4 100644 --- a/src/codegen/ia32/macro-assembler-ia32.cc +++ b/src/codegen/ia32/macro-assembler-ia32.cc @@ -2548,9 +2548,17 @@ void TurboAssembler::CallCodeObject(Register code_object) { call(code_object); } -void TurboAssembler::JumpCodeObject(Register code_object) { +void TurboAssembler::JumpCodeObject(Register code_object, JumpMode jump_mode) { LoadCodeObjectEntry(code_object, code_object); - jmp(code_object); + switch (jump_mode) { + case JumpMode::kJump: + jmp(code_object); + return; + case JumpMode::kPushAndReturn: + push(code_object); + ret(0); + return; + } } void TurboAssembler::Jump(const ExternalReference& reference) { diff --git a/src/codegen/ia32/macro-assembler-ia32.h b/src/codegen/ia32/macro-assembler-ia32.h index c09002e1cf..fea3d30700 100644 --- a/src/codegen/ia32/macro-assembler-ia32.h +++ b/src/codegen/ia32/macro-assembler-ia32.h @@ -145,7 +145,8 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase { void LoadCodeObjectEntry(Register destination, Register code_object) override; void CallCodeObject(Register code_object) override; - void JumpCodeObject(Register code_object) override; + void JumpCodeObject(Register code_object, + JumpMode jump_mode = JumpMode::kJump) override; void Jump(const ExternalReference& reference) override; void RetpolineCall(Register reg); diff --git a/src/codegen/turbo-assembler.h b/src/codegen/turbo-assembler.h index 5c6bb70acc..cc9ef92919 100644 --- a/src/codegen/turbo-assembler.h +++ b/src/codegen/turbo-assembler.h @@ -15,6 +15,12 @@ namespace v8 { namespace internal { +enum class JumpMode { + kJump, // Does a direct jump to the given address + kPushAndReturn // Pushes the given address as the current return address and + // does a return +}; + // Common base class for platform-specific TurboAssemblers containing // platform-independent bits. // You will encounter two subclasses, TurboAssembler (derives from @@ -67,7 +73,8 @@ class V8_EXPORT_PRIVATE TurboAssemblerBase : public Assembler { // Calls/jumps to the given Code object. If builtins are embedded, the // trampoline Code object on the heap is not used. virtual void CallCodeObject(Register code_object) = 0; - virtual void JumpCodeObject(Register code_object) = 0; + virtual void JumpCodeObject(Register code_object, + JumpMode jump_mode = JumpMode::kJump) = 0; // Loads the given Code object's entry point into the destination register. virtual void LoadCodeObjectEntry(Register destination, diff --git a/src/codegen/x64/macro-assembler-x64.cc b/src/codegen/x64/macro-assembler-x64.cc index 5b4be9c525..2a918b6efb 100644 --- a/src/codegen/x64/macro-assembler-x64.cc +++ b/src/codegen/x64/macro-assembler-x64.cc @@ -1771,9 +1771,17 @@ void TurboAssembler::CallCodeObject(Register code_object) { call(code_object); } -void TurboAssembler::JumpCodeObject(Register code_object) { +void TurboAssembler::JumpCodeObject(Register code_object, JumpMode jump_mode) { LoadCodeObjectEntry(code_object, code_object); - jmp(code_object); + switch (jump_mode) { + case JumpMode::kJump: + jmp(code_object); + return; + case JumpMode::kPushAndReturn: + pushq(code_object); + Ret(); + return; + } } void TurboAssembler::RetpolineCall(Register reg) { diff --git a/src/codegen/x64/macro-assembler-x64.h b/src/codegen/x64/macro-assembler-x64.h index 7ea486428a..bff2b78586 100644 --- a/src/codegen/x64/macro-assembler-x64.h +++ b/src/codegen/x64/macro-assembler-x64.h @@ -531,7 +531,8 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase { void LoadCodeObjectEntry(Register destination, Register code_object) override; void CallCodeObject(Register code_object) override; - void JumpCodeObject(Register code_object) override; + void JumpCodeObject(Register code_object, + JumpMode jump_mode = JumpMode::kJump) override; void RetpolineCall(Register reg); void RetpolineCall(Address destination, RelocInfo::Mode rmode);