Commit af62c4f0 authored by Simon Zünd's avatar Simon Zünd Committed by V8 LUCI CQ

[sparkplug] Allow sparkplug->ignition deopt in func entry

Adapted from https://crrev.com/c/3862264.

Add a new teardown trampoline for the case where a Sparkplug function is
deoptimized during its function entry stack check. In these cases, the
stack is in an incomplete setup state, so instead of forwarding to
interpreter re-entry, we undo the partial stack setup and forward to
the standard interpreter entry.

R=leszeks@chromium.org

Bug: chromium:1246907, chromium:1357554
Change-Id: I0795b20cdc60d3ba28bc32cd55bdf82d72f83aac
Also-by: leszeks@chromium.org
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3865144
Commit-Queue: Simon Zünd <szuend@chromium.org>
Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/main@{#82811}
parent 810a0b5f
......@@ -1073,6 +1073,26 @@ void Builtins::Generate_BaselineOutOfLinePrologue(MacroAssembler* masm) {
__ Ret();
}
// static
void Builtins::Generate_BaselineOutOfLinePrologueDeopt(MacroAssembler* masm) {
// We're here because we got deopted during BaselineOutOfLinePrologue's stack
// check. Undo all its frame creation and call into the interpreter instead.
// Drop bytecode offset (was the feedback vector but got replaced during
// deopt) and bytecode array.
__ Drop(2);
// Context, closure, argc.
__ Pop(kContextRegister, kJavaScriptCallTargetRegister,
kJavaScriptCallArgCountRegister);
// Drop frame pointer
__ LeaveFrame(StackFrame::BASELINE);
// Enter the interpreter.
__ TailCallBuiltin(Builtin::kInterpreterEntryTrampoline);
}
// Generate code for entering a JS function with the interpreter.
// On entry to the function the receiver and arguments have been pushed on the
// stack left to right.
......
......@@ -1226,6 +1226,27 @@ void Builtins::Generate_BaselineOutOfLinePrologue(MacroAssembler* masm) {
__ Ret();
}
// static
void Builtins::Generate_BaselineOutOfLinePrologueDeopt(MacroAssembler* masm) {
// We're here because we got deopted during BaselineOutOfLinePrologue's stack
// check. Undo all its frame creation and call into the interpreter instead.
// Drop the accumulator register (we already started building the register
// frame) and bytecode offset (was the feedback vector but got replaced
// during deopt).
__ Drop(2);
// Bytecode array, argc, Closure, Context.
__ Pop(padreg, kJavaScriptCallArgCountRegister, kJavaScriptCallTargetRegister,
kContextRegister);
// Drop frame pointer
__ LeaveFrame(StackFrame::BASELINE);
// Enter the interpreter.
__ TailCallBuiltin(Builtin::kInterpreterEntryTrampoline);
}
// Generate code for entering a JS function with the interpreter.
// On entry to the function the receiver and arguments have been pushed on the
// stack left to right.
......
......@@ -189,6 +189,7 @@ namespace internal {
\
/* Baseline Compiler */ \
ASM(BaselineOutOfLinePrologue, BaselineOutOfLinePrologue) \
ASM(BaselineOutOfLinePrologueDeopt, Void) \
ASM(BaselineOnStackReplacement, BaselineOnStackReplacement) \
ASM(BaselineLeaveFrame, BaselineLeaveFrame) \
ASM(BaselineOrInterpreterEnterAtBytecode, Void) \
......
......@@ -348,6 +348,7 @@ V8_INLINE constexpr bool IsBaselineTrampolineBuiltin(Builtin builtin_id) {
// is not a builtin.
return builtin_id != Builtin::kNoBuiltinId &&
(builtin_id == Builtin::kBaselineOutOfLinePrologue ||
builtin_id == Builtin::kBaselineOutOfLinePrologueDeopt ||
builtin_id == Builtin::kBaselineOrInterpreterEnterAtBytecode ||
builtin_id == Builtin::kBaselineOrInterpreterEnterAtNextBytecode);
}
......
......@@ -1670,6 +1670,31 @@ void Builtins::Generate_BaselineOutOfLinePrologue(MacroAssembler* masm) {
}
}
// static
void Builtins::Generate_BaselineOutOfLinePrologueDeopt(MacroAssembler* masm) {
// We're here because we got deopted during BaselineOutOfLinePrologue's stack
// check. Undo all its frame creation and call into the interpreter instead.
// Drop bytecode offset (was the feedback vector but got replaced during
// deopt).
__ Pop(ecx);
// Drop bytecode array
__ Pop(ecx);
// argc.
__ Pop(kJavaScriptCallArgCountRegister);
// Closure.
__ Pop(kJavaScriptCallTargetRegister);
// Context.
__ Pop(kContextRegister);
// Drop frame pointer
__ LeaveFrame(StackFrame::BASELINE);
// Enter the interpreter.
__ TailCallBuiltin(Builtin::kInterpreterEntryTrampoline);
}
namespace {
void Generate_ContinueToBuiltinHelper(MacroAssembler* masm,
bool java_script_builtin,
......
......@@ -1657,6 +1657,31 @@ void Builtins::Generate_BaselineOutOfLinePrologue(MacroAssembler* masm) {
}
}
// static
void Builtins::Generate_BaselineOutOfLinePrologueDeopt(MacroAssembler* masm) {
// We're here because we got deopted during BaselineOutOfLinePrologue's stack
// check. Undo all its frame creation and call into the interpreter instead.
// Drop bytecode offset (was the feedback vector but got replaced during
// deopt).
__ Pop(kScratchRegister);
// Drop bytecode array
__ Pop(kScratchRegister);
// argc.
__ Pop(kJavaScriptCallArgCountRegister);
// Closure.
__ Pop(kJavaScriptCallTargetRegister);
// Context.
__ Pop(kContextRegister);
// Drop frame pointer
__ LeaveFrame(StackFrame::BASELINE);
// Enter the interpreter.
__ TailCallBuiltin(Builtin::kInterpreterEntryTrampoline);
}
namespace {
void Generate_ContinueToBuiltinHelper(MacroAssembler* masm,
bool java_script_builtin,
......
......@@ -1414,8 +1414,14 @@ class DiscardBaselineCodeVisitor : public ThreadVisitor {
BaselineFrame* frame = BaselineFrame::cast(it.frame());
int bytecode_offset = frame->GetBytecodeOffset();
Address* pc_addr = frame->pc_address();
Address advance = BUILTIN_CODE(isolate, InterpreterEnterAtNextBytecode)
->InstructionStart();
Address advance;
if (bytecode_offset == kFunctionEntryBytecodeOffset) {
advance = BUILTIN_CODE(isolate, BaselineOutOfLinePrologueDeopt)
->InstructionStart();
} else {
advance = BUILTIN_CODE(isolate, InterpreterEnterAtNextBytecode)
->InstructionStart();
}
PointerAuthentication::ReplacePC(pc_addr, advance, kSystemPointerSize);
InterpretedFrame::cast(it.Reframe())
->PatchBytecodeOffset(bytecode_offset);
......
......@@ -2,10 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// TODO(crbug.com/1357554): Enable for Sparkplug once we can step into a
// a sparkplug function paused during the sparkplug prolog builtin.
// Flags: --no-sparkplug
// Flags: --always-sparkplug
var Debug = debug.Debug;
......@@ -18,5 +15,6 @@ Debug.setListener(function (event, exec_state, event_data, data) {
%ScheduleBreak();
(function foo() {
return 5;
const x = 5;
() => x; // context-allocate x.
})();
......@@ -154,11 +154,4 @@
'regress/regress-crbug-507070': [SKIP],
}], # third_party_heap
################################################################################
['variant == sparkplug or variant == always_sparkplug', {
# https://crbug.com/1357554: Enable for Sparkplug once we can step into a
# a sparkplug function paused during the sparkplug prolog builtin.
'debug/regress/regress-crbug-1357554': [SKIP],
}], # variant == sparkplug or variant == always_sparkplug
]
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment