[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:
parent
aedb95efb9
commit
af3c5307f0
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user