@@ -1784,6 +1784,20 @@ void Builtins::Generate_TailCallOptimizedCodeSlot(MacroAssembler* masm) {
17841784}
17851785
17861786namespace {
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+
17871801void 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, ¬_jump_loop);
3538- __ Move (get_baseline_pc,
3539- ExternalReference::baseline_start_pc_for_bytecode_offset ());
3540- __ bind (¬_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+
35843620void Builtins::Generate_DynamicCheckMapsTrampoline (MacroAssembler* masm) {
35853621 FrameScope scope (masm, StackFrame::MANUAL );
35863622 __ EnterFrame (StackFrame::INTERNAL );
0 commit comments