| Index: src/builtins/x64/builtins-x64.cc
|
| diff --git a/src/builtins/x64/builtins-x64.cc b/src/builtins/x64/builtins-x64.cc
|
| index 87dfc7d3a6b6305a4d7ec63c05c36e47b5418a7c..16e9d00cf56e96ca24953e9f5558c5f67f5844a8 100644
|
| --- a/src/builtins/x64/builtins-x64.cc
|
| +++ b/src/builtins/x64/builtins-x64.cc
|
| @@ -559,6 +559,132 @@ void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
|
| __ jmp(&stepping_prepared);
|
| }
|
|
|
| +// static
|
| +void Builtins::Generate_ResumeAwaitedGeneratorTrampoline(MacroAssembler* masm) {
|
| + // ----------- S t a t e -------------
|
| + // -- rax : the value to pass to the generator
|
| + // -- rbx : the JSGeneratorObject to resume
|
| + // -- rdx : the resume mode (tagged)
|
| + // -- rsp[0] : return address
|
| + // -----------------------------------
|
| + __ AssertGeneratorObject(rbx);
|
| +
|
| + // Restore saved input
|
| + __ movp(rcx, FieldOperand(rbx, JSGeneratorObject::kAwaitInputOffset));
|
| + __ movp(FieldOperand(rbx, JSGeneratorObject::kInputOrDebugPosOffset), rcx);
|
| + __ RecordWriteField(rbx, JSGeneratorObject::kInputOrDebugPosOffset, rcx, rsi,
|
| + kDontSaveFPRegs);
|
| +
|
| + // Store input value into generator object.
|
| + __ movp(FieldOperand(rbx, JSGeneratorObject::kAwaitInputOffset), rax);
|
| + __ RecordWriteField(rbx, JSGeneratorObject::kAwaitInputOffset, rax, rcx,
|
| + kDontSaveFPRegs);
|
| +
|
| + // Store resume mode into generator object.
|
| + __ movp(FieldOperand(rbx, JSGeneratorObject::kResumeModeOffset), rdx);
|
| +
|
| + // Load suspended function and context.
|
| + __ movp(rsi, FieldOperand(rbx, JSGeneratorObject::kContextOffset));
|
| + __ movp(rdi, FieldOperand(rbx, JSGeneratorObject::kFunctionOffset));
|
| +
|
| + // Flood function if we are stepping.
|
| + Label prepare_step_in_if_stepping, prepare_step_in_suspended_generator;
|
| + Label stepping_prepared;
|
| + ExternalReference last_step_action =
|
| + ExternalReference::debug_last_step_action_address(masm->isolate());
|
| + Operand last_step_action_operand = masm->ExternalOperand(last_step_action);
|
| + STATIC_ASSERT(StepFrame > StepIn);
|
| + __ cmpb(last_step_action_operand, Immediate(StepIn));
|
| + __ j(greater_equal, &prepare_step_in_if_stepping);
|
| +
|
| + // Flood function if we need to continue stepping in the suspended generator.
|
| + ExternalReference debug_suspended_generator =
|
| + ExternalReference::debug_suspended_generator_address(masm->isolate());
|
| + Operand debug_suspended_generator_operand =
|
| + masm->ExternalOperand(debug_suspended_generator);
|
| + __ cmpp(rbx, debug_suspended_generator_operand);
|
| + __ j(equal, &prepare_step_in_suspended_generator);
|
| + __ bind(&stepping_prepared);
|
| +
|
| + // Pop return address.
|
| + __ PopReturnAddressTo(rax);
|
| +
|
| + // Push receiver.
|
| + __ Push(FieldOperand(rbx, JSGeneratorObject::kReceiverOffset));
|
| +
|
| + // ----------- S t a t e -------------
|
| + // -- rax : return address
|
| + // -- rbx : the JSGeneratorObject to resume
|
| + // -- rdx : the resume mode (tagged)
|
| + // -- rdi : generator function
|
| + // -- rsi : generator context
|
| + // -- rsp[0] : generator receiver
|
| + // -----------------------------------
|
| +
|
| + // Push holes for arguments to generator function. Since the parser forced
|
| + // context allocation for any variables in generators, the actual argument
|
| + // values have already been copied into the context and these dummy values
|
| + // will never be used.
|
| + __ movp(rcx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
|
| + __ LoadSharedFunctionInfoSpecialField(
|
| + rcx, rcx, SharedFunctionInfo::kFormalParameterCountOffset);
|
| + {
|
| + Label done_loop, loop;
|
| + __ bind(&loop);
|
| + __ subl(rcx, Immediate(1));
|
| + __ j(carry, &done_loop, Label::kNear);
|
| + __ PushRoot(Heap::kTheHoleValueRootIndex);
|
| + __ jmp(&loop);
|
| + __ bind(&done_loop);
|
| + }
|
| +
|
| + // Underlying function needs to have bytecode available.
|
| + if (FLAG_debug_code) {
|
| + __ movp(rcx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
|
| + __ movp(rcx, FieldOperand(rcx, SharedFunctionInfo::kFunctionDataOffset));
|
| + __ CmpObjectType(rcx, BYTECODE_ARRAY_TYPE, rcx);
|
| + __ Assert(equal, kMissingBytecodeArray);
|
| + }
|
| +
|
| + // Resume (Ignition/TurboFan) generator object.
|
| + {
|
| + __ PushReturnAddressFrom(rax);
|
| + __ movp(rax, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
|
| + __ LoadSharedFunctionInfoSpecialField(
|
| + rax, rax, SharedFunctionInfo::kFormalParameterCountOffset);
|
| + // We abuse new.target both to indicate that this is a resume call and to
|
| + // pass in the generator object. In ordinary calls, new.target is always
|
| + // undefined because generator functions are non-constructable.
|
| + __ movp(rdx, rbx);
|
| + __ jmp(FieldOperand(rdi, JSFunction::kCodeEntryOffset));
|
| + }
|
| +
|
| + __ bind(&prepare_step_in_if_stepping);
|
| + {
|
| + FrameScope scope(masm, StackFrame::INTERNAL);
|
| + __ Push(rbx);
|
| + __ Push(rdx);
|
| + __ Push(rdi);
|
| + __ CallRuntime(Runtime::kDebugPrepareStepInIfStepping);
|
| + __ Pop(rdx);
|
| + __ Pop(rbx);
|
| + __ movp(rdi, FieldOperand(rbx, JSGeneratorObject::kFunctionOffset));
|
| + }
|
| + __ jmp(&stepping_prepared);
|
| +
|
| + __ bind(&prepare_step_in_suspended_generator);
|
| + {
|
| + FrameScope scope(masm, StackFrame::INTERNAL);
|
| + __ Push(rbx);
|
| + __ Push(rdx);
|
| + __ CallRuntime(Runtime::kDebugPrepareStepInSuspendedGenerator);
|
| + __ Pop(rdx);
|
| + __ Pop(rbx);
|
| + __ movp(rdi, FieldOperand(rbx, JSGeneratorObject::kFunctionOffset));
|
| + }
|
| + __ jmp(&stepping_prepared);
|
| +}
|
| +
|
| static void LeaveInterpreterFrame(MacroAssembler* masm, Register scratch1,
|
| Register scratch2) {
|
| Register args_count = scratch1;
|
|
|