| Index: src/arm/builtins-arm.cc
|
| diff --git a/src/arm/builtins-arm.cc b/src/arm/builtins-arm.cc
|
| index 1fffcb67e596dd76147c9b4808358b491c90722e..feb12319f84619b281d7d8f0a0d4e85519e2d63f 100644
|
| --- a/src/arm/builtins-arm.cc
|
| +++ b/src/arm/builtins-arm.cc
|
| @@ -704,6 +704,116 @@ void Builtins::Generate_JSBuiltinsConstructStubForDerived(
|
| Generate_JSConstructStubHelper(masm, false, false, true);
|
| }
|
|
|
| +// static
|
| +void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
|
| + // ----------- S t a t e -------------
|
| + // -- r0 : the value to pass to the generator
|
| + // -- r1 : the JSGeneratorObject to resume
|
| + // -- r2 : the resume mode (tagged)
|
| + // -- lr : return address
|
| + // -----------------------------------
|
| + __ AssertGeneratorObject(r1);
|
| +
|
| + // Store input value into generator object.
|
| + __ str(r0, FieldMemOperand(r1, JSGeneratorObject::kInputOffset));
|
| + __ RecordWriteField(r1, JSGeneratorObject::kInputOffset, r0, r3,
|
| + kLRHasNotBeenSaved, kDontSaveFPRegs);
|
| +
|
| + // Load suspended function and context.
|
| + __ ldr(cp, FieldMemOperand(r1, JSGeneratorObject::kContextOffset));
|
| + __ ldr(r4, FieldMemOperand(r1, JSGeneratorObject::kFunctionOffset));
|
| +
|
| + // Flood function if we are stepping.
|
| + Label skip_flooding;
|
| + ExternalReference step_in_enabled =
|
| + ExternalReference::debug_step_in_enabled_address(masm->isolate());
|
| + __ mov(ip, Operand(step_in_enabled));
|
| + __ ldrb(ip, MemOperand(ip));
|
| + __ cmp(ip, Operand(0));
|
| + __ b(eq, &skip_flooding);
|
| + {
|
| + FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
|
| + __ Push(r1, r2, r4);
|
| + __ CallRuntime(Runtime::kDebugPrepareStepInIfStepping);
|
| + __ Pop(r1, r2);
|
| + __ ldr(r4, FieldMemOperand(r1, JSGeneratorObject::kFunctionOffset));
|
| + }
|
| + __ bind(&skip_flooding);
|
| +
|
| + // Push receiver.
|
| + __ ldr(ip, FieldMemOperand(r1, JSGeneratorObject::kReceiverOffset));
|
| + __ Push(ip);
|
| +
|
| + // ----------- S t a t e -------------
|
| + // -- r1 : the JSGeneratorObject to resume
|
| + // -- r2 : the resume mode (tagged)
|
| + // -- r4 : generator function
|
| + // -- cp : generator context
|
| + // -- lr : return address
|
| + // -- sp[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.
|
| + __ ldr(r3, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
|
| + __ ldr(r3,
|
| + FieldMemOperand(r3, SharedFunctionInfo::kFormalParameterCountOffset));
|
| + {
|
| + Label done_loop, loop;
|
| + __ bind(&loop);
|
| + __ sub(r3, r3, Operand(Smi::FromInt(1)), SetCC);
|
| + __ b(mi, &done_loop);
|
| + __ PushRoot(Heap::kTheHoleValueRootIndex);
|
| + __ b(&loop);
|
| + __ bind(&done_loop);
|
| + }
|
| +
|
| + // Enter a new JavaScript frame, and initialize its slots as they were when
|
| + // the generator was suspended.
|
| + DCHECK(!FLAG_enable_embedded_constant_pool);
|
| + FrameScope scope(masm, StackFrame::MANUAL);
|
| + __ Push(lr, fp);
|
| + __ Move(fp, sp);
|
| + __ Push(cp, r4);
|
| +
|
| + // Restore the operand stack.
|
| + __ ldr(r0, FieldMemOperand(r1, JSGeneratorObject::kOperandStackOffset));
|
| + __ ldr(r3, FieldMemOperand(r0, FixedArray::kLengthOffset));
|
| + __ add(r0, r0, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
|
| + __ add(r3, r0, Operand(r3, LSL, kPointerSizeLog2 - 1));
|
| + {
|
| + Label done_loop, loop;
|
| + __ bind(&loop);
|
| + __ cmp(r0, r3);
|
| + __ b(eq, &done_loop);
|
| + __ ldr(ip, MemOperand(r0, kPointerSize, PostIndex));
|
| + __ Push(ip);
|
| + __ b(&loop);
|
| + __ bind(&done_loop);
|
| + }
|
| +
|
| + // Push resume mode (consumed in continuation).
|
| + __ Push(r2);
|
| +
|
| + // Reset operand stack so we don't leak.
|
| + __ LoadRoot(ip, Heap::kEmptyFixedArrayRootIndex);
|
| + __ str(ip, FieldMemOperand(r1, JSGeneratorObject::kOperandStackOffset));
|
| +
|
| + // Restore value.
|
| + __ ldr(r0, FieldMemOperand(r1, JSGeneratorObject::kInputOffset));
|
| +
|
| + // Resume the generator function at the continuation.
|
| + __ ldr(r3, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
|
| + __ ldr(r3, FieldMemOperand(r3, SharedFunctionInfo::kCodeOffset));
|
| + __ add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag));
|
| + __ ldr(r2, FieldMemOperand(r1, JSGeneratorObject::kContinuationOffset));
|
| + __ add(r3, r3, Operand(r2, ASR, 1));
|
| + __ mov(r2, Operand(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)));
|
| + __ str(r2, FieldMemOperand(r1, JSGeneratorObject::kContinuationOffset));
|
| + __ Jump(r3);
|
| +}
|
|
|
| void Builtins::Generate_ConstructedNonConstructable(MacroAssembler* masm) {
|
| FrameScope scope(masm, StackFrame::INTERNAL);
|
|
|