[sparkplug] Use return to jump to optimized code to keep the RSB balanced

This threads through a JumpMode kJump/kReturn to JumpCodeObject so we
can use a return instruction to jump instead by first pushing the jump
target and then using a return instruction.

Bug: v8:11429
Change-Id: I8658ed9c5bade28bd6efc76e26fd92bad22b3c68
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2697196
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
Auto-Submit: Toon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/master@{#72804}
This commit is contained in:
Toon Verwaest 2021-02-17 11:08:22 +01:00 committed by Commit Bot
parent aedb95efb9
commit af3c5307f0
10 changed files with 60 additions and 24 deletions

View File

@ -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

View File

@ -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);
}

View File

@ -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.

View File

@ -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);

View File

@ -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.

View File

@ -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) {

View File

@ -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);

View File

@ -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,

View File

@ -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) {

View File

@ -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);