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); |