Skip to content

Commit 064ca18

Browse files
Patrick ThierCommit Bot
authored andcommitted
Reland "[sparkplug] OSR Ignition -> Sparkplug"
This is a reland of b9c521d. Fixes crashes by calling kInstallBaselineCode from BaselineEntry if needed, i.e. when there is no feedback vector (required a bit of register rejiggling). This can happen with cross-realm calls. The OSR arming is stored as part of the BytecodeArray and therefore shared across realms. Original change's description: > [sparkplug] OSR Ignition -> Sparkplug > > Add support for OSR to baseline code. > We compile baseline and perform OSR immediately when the bytecode budget > interrupt hits. > > Drive-by: Clean-up deoptimizer special handling of JumpLoop by using > the newly introduced GetBaselinePCForNextExecutedBytecode instead of > GetBaselineEndPCForBytecodeOffset. > > Bug: v8:11420 > Change-Id: Ifbea264d4a83a127dd2a11e28626bf2a5e8aca59 > Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2784687 > Commit-Queue: Patrick Thier <pthier@chromium.org> > Reviewed-by: Leszek Swirski <leszeks@chromium.org> > Cr-Commit-Position: refs/heads/master@{#73677} Bug: v8:11420 Change-Id: I67325450514ed5a1170b730b1dd59fa6acc6e1d8 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2800112 Reviewed-by: Jakob Gruber <jgruber@chromium.org> Commit-Queue: Patrick Thier <pthier@chromium.org> Cr-Commit-Position: refs/heads/master@{#73803}
1 parent d0778a8 commit 064ca18

15 files changed

Lines changed: 460 additions & 256 deletions

src/builtins/arm/builtins-arm.cc

Lines changed: 93 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1784,6 +1784,20 @@ void Builtins::Generate_TailCallOptimizedCodeSlot(MacroAssembler* masm) {
17841784
}
17851785

17861786
namespace {
1787+
1788+
void Generate_OSREntry(MacroAssembler* masm, Register entry_address,
1789+
Operand offset = Operand::Zero()) {
1790+
// Compute the target address = entry_address + offset
1791+
if (offset.IsImmediate() && offset.immediate() == 0) {
1792+
__ mov(lr, entry_address);
1793+
} else {
1794+
__ add(lr, entry_address, offset);
1795+
}
1796+
1797+
// "return" to the OSR entry point of the function.
1798+
__ Ret();
1799+
}
1800+
17871801
void OnStackReplacement(MacroAssembler* masm, bool is_interpreter) {
17881802
{
17891803
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
@@ -1817,11 +1831,7 @@ void OnStackReplacement(MacroAssembler* masm, bool is_interpreter) {
18171831
__ ldr(r1, FieldMemOperand(r1, FixedArray::OffsetOfElementAt(
18181832
DeoptimizationData::kOsrPcOffsetIndex)));
18191833

1820-
// Compute the target address = code start + osr_offset
1821-
__ add(lr, r0, Operand::SmiUntag(r1));
1822-
1823-
// And "return" to the OSR entry point of the function.
1824-
__ Ret();
1834+
Generate_OSREntry(masm, r0, Operand::SmiUntag(r1));
18251835
}
18261836
}
18271837
} // namespace
@@ -3466,30 +3476,34 @@ namespace {
34663476

34673477
// Converts an interpreter frame into a baseline frame and continues execution
34683478
// in baseline code (baseline code has to exist on the shared function info),
3469-
// either at the start or the end of the current bytecode.
3470-
void Generate_BaselineEntry(MacroAssembler* masm, bool next_bytecode) {
3471-
// Get bytecode array and bytecode offset from the stack frame.
3472-
__ ldr(kInterpreterBytecodeArrayRegister,
3473-
MemOperand(fp, InterpreterFrameConstants::kBytecodeArrayFromFp));
3474-
__ ldr(kInterpreterBytecodeOffsetRegister,
3475-
MemOperand(fp, InterpreterFrameConstants::kBytecodeOffsetFromFp));
3476-
__ SmiUntag(kInterpreterBytecodeOffsetRegister);
3479+
// either at the current or next (in execution order) bytecode.
3480+
void Generate_BaselineEntry(MacroAssembler* masm, bool next_bytecode,
3481+
bool is_osr = false) {
3482+
__ Push(kInterpreterAccumulatorRegister);
3483+
Label start;
3484+
__ bind(&start);
34773485

34783486
// Get function from the frame.
34793487
Register closure = r1;
34803488
__ ldr(closure, MemOperand(fp, StandardFrameConstants::kFunctionOffset));
34813489

3482-
// Replace BytecodeOffset with the feedback vector.
3490+
// Load the feedback vector.
34833491
Register feedback_vector = r2;
34843492
__ ldr(feedback_vector,
34853493
FieldMemOperand(closure, JSFunction::kFeedbackCellOffset));
34863494
__ ldr(feedback_vector, FieldMemOperand(feedback_vector, Cell::kValueOffset));
3487-
if (__ emit_debug_code()) {
3488-
Register scratch = r3;
3489-
__ CompareObjectType(feedback_vector, scratch, scratch,
3490-
FEEDBACK_VECTOR_TYPE);
3491-
__ Assert(eq, AbortReason::kExpectedFeedbackVector);
3492-
}
3495+
3496+
Label install_baseline_code;
3497+
// Check if feedback vector is valid. If not, call prepare for baseline to
3498+
// allocate it.
3499+
__ CompareObjectType(feedback_vector, r3, r3, FEEDBACK_VECTOR_TYPE);
3500+
__ b(ne, &install_baseline_code);
3501+
3502+
// Save BytecodeOffset from the stack frame.
3503+
__ ldr(kInterpreterBytecodeOffsetRegister,
3504+
MemOperand(fp, InterpreterFrameConstants::kBytecodeOffsetFromFp));
3505+
__ SmiUntag(kInterpreterBytecodeOffsetRegister);
3506+
// Replace BytecodeOffset with the feedback vector.
34933507
__ str(feedback_vector,
34943508
MemOperand(fp, InterpreterFrameConstants::kBytecodeOffsetFromFp));
34953509
feedback_vector = no_reg;
@@ -3502,14 +3516,16 @@ void Generate_BaselineEntry(MacroAssembler* masm, bool next_bytecode) {
35023516
FieldMemOperand(code_obj, SharedFunctionInfo::kFunctionDataOffset));
35033517
__ ldr(code_obj,
35043518
FieldMemOperand(code_obj, BaselineData::kBaselineCodeOffset));
3505-
closure = no_reg;
35063519

35073520
// Compute baseline pc for bytecode offset.
3508-
__ Push(kInterpreterAccumulatorRegister);
3509-
ExternalReference get_baseline_pc_extref =
3510-
next_bytecode
3511-
? ExternalReference::baseline_end_pc_for_bytecode_offset()
3512-
: ExternalReference::baseline_start_pc_for_bytecode_offset();
3521+
ExternalReference get_baseline_pc_extref;
3522+
if (next_bytecode || is_osr) {
3523+
get_baseline_pc_extref =
3524+
ExternalReference::baseline_pc_for_next_executed_bytecode();
3525+
} else {
3526+
get_baseline_pc_extref =
3527+
ExternalReference::baseline_pc_for_bytecode_offset();
3528+
}
35133529
Register get_baseline_pc = r3;
35143530
__ Move(get_baseline_pc, get_baseline_pc_extref);
35153531

@@ -3519,56 +3535,71 @@ void Generate_BaselineEntry(MacroAssembler* masm, bool next_bytecode) {
35193535
// TODO(pthier): Investigate if it is feasible to handle this special case
35203536
// in TurboFan instead of here.
35213537
Label valid_bytecode_offset, function_entry_bytecode;
3522-
__ cmp(kInterpreterBytecodeOffsetRegister,
3523-
Operand(BytecodeArray::kHeaderSize - kHeapObjectTag +
3524-
kFunctionEntryBytecodeOffset));
3525-
__ b(eq, &function_entry_bytecode);
3526-
__ bind(&valid_bytecode_offset);
3527-
3528-
// In the case we advance the BC, check if the current bytecode is JumpLoop.
3529-
// If it is, re-execute it instead of continuing at the next bytecode.
3530-
if (next_bytecode) {
3531-
Label not_jump_loop;
3532-
Register bytecode = r1;
3533-
__ ldrb(bytecode, MemOperand(kInterpreterBytecodeArrayRegister,
3534-
kInterpreterBytecodeOffsetRegister));
3535-
__ cmp(bytecode,
3536-
Operand(static_cast<int>(interpreter::Bytecode::kJumpLoop)));
3537-
__ b(ne, &not_jump_loop);
3538-
__ Move(get_baseline_pc,
3539-
ExternalReference::baseline_start_pc_for_bytecode_offset());
3540-
__ bind(&not_jump_loop);
3538+
if (!is_osr) {
3539+
__ cmp(kInterpreterBytecodeOffsetRegister,
3540+
Operand(BytecodeArray::kHeaderSize - kHeapObjectTag +
3541+
kFunctionEntryBytecodeOffset));
3542+
__ b(eq, &function_entry_bytecode);
35413543
}
35423544

35433545
__ sub(kInterpreterBytecodeOffsetRegister, kInterpreterBytecodeOffsetRegister,
35443546
Operand(BytecodeArray::kHeaderSize - kHeapObjectTag));
35453547

3548+
__ bind(&valid_bytecode_offset);
3549+
// Get bytecode array from the stack frame.
3550+
__ ldr(kInterpreterBytecodeArrayRegister,
3551+
MemOperand(fp, InterpreterFrameConstants::kBytecodeArrayFromFp));
35463552
{
3547-
FrameScope scope(masm, StackFrame::INTERNAL);
3548-
__ PrepareCallCFunction(3, 0, r0);
35493553
Register arg_reg_1 = r0;
35503554
Register arg_reg_2 = r1;
35513555
Register arg_reg_3 = r2;
35523556
__ mov(arg_reg_1, code_obj);
35533557
__ mov(arg_reg_2, kInterpreterBytecodeOffsetRegister);
35543558
__ mov(arg_reg_3, kInterpreterBytecodeArrayRegister);
3559+
FrameScope scope(masm, StackFrame::INTERNAL);
3560+
__ PrepareCallCFunction(3, 0);
35553561
__ CallCFunction(get_baseline_pc, 3, 0);
35563562
}
3557-
__ add(code_obj, code_obj, Operand(Code::kHeaderSize - kHeapObjectTag));
35583563
__ add(code_obj, code_obj, kReturnRegister0);
35593564
__ Pop(kInterpreterAccumulatorRegister);
35603565

3561-
__ Jump(code_obj);
3566+
if (is_osr) {
3567+
// Reset the OSR loop nesting depth to disarm back edges.
3568+
// TODO(pthier): Separate baseline Sparkplug from TF arming and don't disarm
3569+
// Sparkplug here.
3570+
UseScratchRegisterScope temps(masm);
3571+
Register scratch = temps.Acquire();
3572+
__ mov(scratch, Operand(0));
3573+
__ strh(scratch, FieldMemOperand(kInterpreterBytecodeArrayRegister,
3574+
BytecodeArray::kOsrNestingLevelOffset));
3575+
Generate_OSREntry(masm, code_obj,
3576+
Operand(Code::kHeaderSize - kHeapObjectTag));
3577+
} else {
3578+
__ add(code_obj, code_obj, Operand(Code::kHeaderSize - kHeapObjectTag));
3579+
__ Jump(code_obj);
3580+
}
35623581
__ Trap(); // Unreachable.
35633582

3564-
__ bind(&function_entry_bytecode);
3565-
// If the bytecode offset is kFunctionEntryOffset, get the start address of
3566-
// the first bytecode.
3567-
__ mov(kInterpreterBytecodeOffsetRegister,
3568-
Operand(BytecodeArray::kHeaderSize - kHeapObjectTag));
3569-
__ Move(get_baseline_pc,
3570-
ExternalReference::baseline_start_pc_for_bytecode_offset());
3571-
__ b(&valid_bytecode_offset);
3583+
if (!is_osr) {
3584+
__ bind(&function_entry_bytecode);
3585+
// If the bytecode offset is kFunctionEntryOffset, get the start address of
3586+
// the first bytecode.
3587+
__ mov(kInterpreterBytecodeOffsetRegister, Operand(0));
3588+
if (next_bytecode) {
3589+
__ Move(get_baseline_pc,
3590+
ExternalReference::baseline_pc_for_bytecode_offset());
3591+
}
3592+
__ b(&valid_bytecode_offset);
3593+
}
3594+
3595+
__ bind(&install_baseline_code);
3596+
{
3597+
FrameScope scope(masm, StackFrame::INTERNAL);
3598+
__ Push(closure);
3599+
__ CallRuntime(Runtime::kInstallBaselineCode, 1);
3600+
}
3601+
// Retry from the start after installing baseline code.
3602+
__ b(&start);
35723603
}
35733604

35743605
} // namespace
@@ -3581,6 +3612,11 @@ void Builtins::Generate_BaselineEnterAtNextBytecode(MacroAssembler* masm) {
35813612
Generate_BaselineEntry(masm, true);
35823613
}
35833614

3615+
void Builtins::Generate_InterpreterOnStackReplacement_ToBaseline(
3616+
MacroAssembler* masm) {
3617+
Generate_BaselineEntry(masm, false, true);
3618+
}
3619+
35843620
void Builtins::Generate_DynamicCheckMapsTrampoline(MacroAssembler* masm) {
35853621
FrameScope scope(masm, StackFrame::MANUAL);
35863622
__ EnterFrame(StackFrame::INTERNAL);

0 commit comments

Comments
 (0)