Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(76)

Side by Side Diff: src/full-codegen/arm64/full-codegen-arm64.cc

Issue 1865833002: [generators] Decouple generator resume from fullcodegen. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #if V8_TARGET_ARCH_ARM64 5 #if V8_TARGET_ARCH_ARM64
6 6
7 #include "src/ast/scopes.h" 7 #include "src/ast/scopes.h"
8 #include "src/code-factory.h" 8 #include "src/code-factory.h"
9 #include "src/code-stubs.h" 9 #include "src/code-stubs.h"
10 #include "src/codegen.h" 10 #include "src/codegen.h"
(...skipping 3726 matching lines...) Expand 10 before | Expand all | Expand 10 after
3737 SetExpressionPosition(expr); 3737 SetExpressionPosition(expr);
3738 3738
3739 // Evaluate yielded value first; the initial iterator definition depends on 3739 // Evaluate yielded value first; the initial iterator definition depends on
3740 // this. It stays on the stack while we update the iterator. 3740 // this. It stays on the stack while we update the iterator.
3741 VisitForStackValue(expr->expression()); 3741 VisitForStackValue(expr->expression());
3742 3742
3743 // TODO(jbramley): Tidy this up once the merge is done, using named registers 3743 // TODO(jbramley): Tidy this up once the merge is done, using named registers
3744 // and suchlike. The implementation changes a little by bleeding_edge so I 3744 // and suchlike. The implementation changes a little by bleeding_edge so I
3745 // don't want to spend too much time on it now. 3745 // don't want to spend too much time on it now.
3746 3746
3747 Label suspend, continuation, post_runtime, resume; 3747 Label suspend, continuation, post_runtime, resume, exception;
3748 3748
3749 __ B(&suspend); 3749 __ B(&suspend);
3750 // TODO(jbramley): This label is bound here because the following code 3750 // TODO(jbramley): This label is bound here because the following code
3751 // looks at its pos(). Is it possible to do something more efficient here, 3751 // looks at its pos(). Is it possible to do something more efficient here,
3752 // perhaps using Adr? 3752 // perhaps using Adr?
3753 __ Bind(&continuation); 3753 __ Bind(&continuation);
3754 // When we arrive here, the stack top is the resume mode and 3754 // When we arrive here, the stack top is the resume mode and
3755 // result_register() holds the input value (the argument given to the 3755 // result_register() holds the input value (the argument given to the
3756 // respective resume operation). 3756 // respective resume operation).
3757 __ RecordGeneratorContinuation(); 3757 __ RecordGeneratorContinuation();
3758 __ Pop(x1); 3758 __ Pop(x1);
3759 __ Cmp(x1, Smi::FromInt(JSGeneratorObject::RETURN)); 3759 STATIC_ASSERT(JSGeneratorObject::kNext < JSGeneratorObject::kReturn);
3760 __ B(ne, &resume); 3760 STATIC_ASSERT(JSGeneratorObject::kThrow > JSGeneratorObject::kReturn);
3761 __ Cmp(x1, Operand(Smi::FromInt(JSGeneratorObject::kReturn)));
3762 __ B(lt, &resume);
3761 __ Push(result_register()); 3763 __ Push(result_register());
3764 __ B(gt, &exception);
3762 EmitCreateIteratorResult(true); 3765 EmitCreateIteratorResult(true);
3763 EmitUnwindAndReturn(); 3766 EmitUnwindAndReturn();
3764 3767
3768 __ Bind(&exception);
3769 __ CallRuntime(Runtime::kThrow);
3770
3765 __ Bind(&suspend); 3771 __ Bind(&suspend);
3766 OperandStackDepthIncrement(1); // Not popped on this path. 3772 OperandStackDepthIncrement(1); // Not popped on this path.
3767 VisitForAccumulatorValue(expr->generator_object()); 3773 VisitForAccumulatorValue(expr->generator_object());
3768 DCHECK((continuation.pos() > 0) && Smi::IsValid(continuation.pos())); 3774 DCHECK((continuation.pos() > 0) && Smi::IsValid(continuation.pos()));
3769 __ Mov(x1, Smi::FromInt(continuation.pos())); 3775 __ Mov(x1, Smi::FromInt(continuation.pos()));
3770 __ Str(x1, FieldMemOperand(x0, JSGeneratorObject::kContinuationOffset)); 3776 __ Str(x1, FieldMemOperand(x0, JSGeneratorObject::kContinuationOffset));
3771 __ Str(cp, FieldMemOperand(x0, JSGeneratorObject::kContextOffset)); 3777 __ Str(cp, FieldMemOperand(x0, JSGeneratorObject::kContextOffset));
3772 __ Mov(x1, cp); 3778 __ Mov(x1, cp);
3773 __ RecordWriteField(x0, JSGeneratorObject::kContextOffset, x1, x2, 3779 __ RecordWriteField(x0, JSGeneratorObject::kContextOffset, x1, x2,
3774 kLRHasBeenSaved, kDontSaveFPRegs); 3780 kLRHasBeenSaved, kDontSaveFPRegs);
3775 __ Add(x1, fp, StandardFrameConstants::kExpressionsOffset); 3781 __ Add(x1, fp, StandardFrameConstants::kExpressionsOffset);
3776 __ Cmp(__ StackPointer(), x1); 3782 __ Cmp(__ StackPointer(), x1);
3777 __ B(eq, &post_runtime); 3783 __ B(eq, &post_runtime);
3778 __ Push(x0); // generator object 3784 __ Push(x0); // generator object
3779 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); 3785 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
3780 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 3786 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
3781 __ Bind(&post_runtime); 3787 __ Bind(&post_runtime);
3782 PopOperand(result_register()); 3788 PopOperand(result_register());
3783 EmitReturnSequence(); 3789 EmitReturnSequence();
3784 3790
3785 __ Bind(&resume); 3791 __ Bind(&resume);
3786 context()->Plug(result_register()); 3792 context()->Plug(result_register());
3787 } 3793 }
3788 3794
3789
3790 void FullCodeGenerator::EmitGeneratorResume(Expression *generator,
3791 Expression *value,
3792 JSGeneratorObject::ResumeMode resume_mode) {
3793 ASM_LOCATION("FullCodeGenerator::EmitGeneratorResume");
3794 Register generator_object = x1;
3795 Register the_hole = x2;
3796 Register operand_stack_size = w3;
3797 Register function = x4;
3798
3799 // The value stays in x0, and is ultimately read by the resumed generator, as
3800 // if CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. Or it
3801 // is read to throw the value when the resumed generator is already closed. x1
3802 // will hold the generator object until the activation has been resumed.
3803 VisitForStackValue(generator);
3804 VisitForAccumulatorValue(value);
3805 PopOperand(generator_object);
3806
3807 // Store input value into generator object.
3808 __ Str(result_register(),
3809 FieldMemOperand(x1, JSGeneratorObject::kInputOffset));
3810 __ Mov(x2, result_register());
3811 __ RecordWriteField(x1, JSGeneratorObject::kInputOffset, x2, x3,
3812 kLRHasBeenSaved, kDontSaveFPRegs);
3813
3814 // Load suspended function and context.
3815 __ Ldr(cp, FieldMemOperand(generator_object,
3816 JSGeneratorObject::kContextOffset));
3817 __ Ldr(function, FieldMemOperand(generator_object,
3818 JSGeneratorObject::kFunctionOffset));
3819
3820 // Load receiver and store as the first argument.
3821 __ Ldr(x10, FieldMemOperand(generator_object,
3822 JSGeneratorObject::kReceiverOffset));
3823 __ Push(x10);
3824
3825 // Push holes for arguments to generator function. Since the parser forced
3826 // context allocation for any variables in generators, the actual argument
3827 // values have already been copied into the context and these dummy values
3828 // will never be used.
3829 __ Ldr(x10, FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset));
3830
3831 // The number of arguments is stored as an int32_t, and -1 is a marker
3832 // (SharedFunctionInfo::kDontAdaptArgumentsSentinel), so we need sign
3833 // extension to correctly handle it. However, in this case, we operate on
3834 // 32-bit W registers, so extension isn't required.
3835 __ Ldr(w10, FieldMemOperand(x10,
3836 SharedFunctionInfo::kFormalParameterCountOffset));
3837 __ LoadRoot(the_hole, Heap::kTheHoleValueRootIndex);
3838 __ PushMultipleTimes(the_hole, w10);
3839
3840 // Enter a new JavaScript frame, and initialize its slots as they were when
3841 // the generator was suspended.
3842 Label resume_frame, done;
3843 __ Bl(&resume_frame);
3844 __ B(&done);
3845
3846 __ Bind(&resume_frame);
3847 __ Push(lr, // Return address.
3848 fp, // Caller's frame pointer.
3849 cp, // Callee's context.
3850 function); // Callee's JS Function.
3851 __ Add(fp, __ StackPointer(), kPointerSize * 2);
3852
3853 // Load and untag the operand stack size.
3854 __ Ldr(x10, FieldMemOperand(generator_object,
3855 JSGeneratorObject::kOperandStackOffset));
3856 __ Ldr(operand_stack_size,
3857 UntagSmiFieldMemOperand(x10, FixedArray::kLengthOffset));
3858
3859 // If we are sending a value and there is no operand stack, we can jump back
3860 // in directly.
3861 if (resume_mode == JSGeneratorObject::NEXT) {
3862 Label slow_resume;
3863 __ Cbnz(operand_stack_size, &slow_resume);
3864 __ Ldr(x10, FieldMemOperand(function, JSFunction::kCodeEntryOffset));
3865 __ Ldrsw(x11,
3866 UntagSmiFieldMemOperand(generator_object,
3867 JSGeneratorObject::kContinuationOffset));
3868 __ Add(x10, x10, x11);
3869 __ Mov(x12, Smi::FromInt(JSGeneratorObject::kGeneratorExecuting));
3870 __ Str(x12, FieldMemOperand(generator_object,
3871 JSGeneratorObject::kContinuationOffset));
3872 __ Push(Smi::FromInt(resume_mode)); // Consumed in continuation.
3873 __ Br(x10);
3874
3875 __ Bind(&slow_resume);
3876 }
3877
3878 // Otherwise, we push holes for the operand stack and call the runtime to fix
3879 // up the stack and the handlers.
3880 __ PushMultipleTimes(the_hole, operand_stack_size);
3881
3882 __ Mov(x10, Smi::FromInt(resume_mode));
3883 __ Push(Smi::FromInt(resume_mode)); // Consumed in continuation.
3884 __ Push(generator_object, result_register(), x10);
3885 __ CallRuntime(Runtime::kResumeJSGeneratorObject);
3886 // Not reached: the runtime call returns elsewhere.
3887 __ Unreachable();
3888
3889 __ Bind(&done);
3890 context()->Plug(result_register());
3891 }
3892
3893 void FullCodeGenerator::PushOperands(Register reg1, Register reg2) { 3795 void FullCodeGenerator::PushOperands(Register reg1, Register reg2) {
3894 OperandStackDepthIncrement(2); 3796 OperandStackDepthIncrement(2);
3895 __ Push(reg1, reg2); 3797 __ Push(reg1, reg2);
3896 } 3798 }
3897 3799
3898 void FullCodeGenerator::PushOperands(Register reg1, Register reg2, 3800 void FullCodeGenerator::PushOperands(Register reg1, Register reg2,
3899 Register reg3) { 3801 Register reg3) {
3900 OperandStackDepthIncrement(3); 3802 OperandStackDepthIncrement(3);
3901 __ Push(reg1, reg2, reg3); 3803 __ Push(reg1, reg2, reg3);
3902 } 3804 }
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after
4153 } 4055 }
4154 4056
4155 return INTERRUPT; 4057 return INTERRUPT;
4156 } 4058 }
4157 4059
4158 4060
4159 } // namespace internal 4061 } // namespace internal
4160 } // namespace v8 4062 } // namespace v8
4161 4063
4162 #endif // V8_TARGET_ARCH_ARM64 4064 #endif // V8_TARGET_ARCH_ARM64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698