| OLD | NEW |
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 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 #include "src/builtins/builtins-utils-gen.h" | 5 #include "src/builtins/builtins-utils-gen.h" |
| 6 #include "src/builtins/builtins.h" | 6 #include "src/builtins/builtins.h" |
| 7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
| 8 #include "src/code-stub-assembler.h" | 8 #include "src/code-stub-assembler.h" |
| 9 #include "src/isolate.h" | 9 #include "src/isolate.h" |
| 10 #include "src/objects-inl.h" | 10 #include "src/objects-inl.h" |
| 11 | 11 |
| 12 namespace v8 { | 12 namespace v8 { |
| 13 namespace internal { | 13 namespace internal { |
| 14 | 14 |
| 15 class GeneratorBuiltinsAssembler : public CodeStubAssembler { | 15 class GeneratorBuiltinsAssembler : public CodeStubAssembler { |
| 16 public: | 16 public: |
| 17 explicit GeneratorBuiltinsAssembler(compiler::CodeAssemblerState* state) | 17 explicit GeneratorBuiltinsAssembler(compiler::CodeAssemblerState* state) |
| 18 : CodeStubAssembler(state) {} | 18 : CodeStubAssembler(state) {} |
| 19 | 19 |
| 20 protected: | 20 protected: |
| 21 void GeneratorPrototypeResume(Node* receiver, Node* value, Node* context, | 21 void GeneratorPrototypeResume(Node* receiver, Node* value, Node* context, |
| 22 JSGeneratorObject::ResumeMode resume_mode, | 22 JSGeneratorObject::ResumeMode resume_mode, |
| 23 char const* const method_name); | 23 char const* const method_name); |
| 24 }; | 24 }; |
| 25 | 25 |
| 26 void GeneratorBuiltinsAssembler::GeneratorPrototypeResume( | 26 void GeneratorBuiltinsAssembler::GeneratorPrototypeResume( |
| 27 Node* receiver, Node* value, Node* context, | 27 Node* receiver, Node* value, Node* context, |
| 28 JSGeneratorObject::ResumeMode resume_mode, char const* const method_name) { | 28 JSGeneratorObject::ResumeMode resume_mode, char const* const method_name) { |
| 29 Node* closed = SmiConstant(JSGeneratorObject::kGeneratorClosed); | |
| 30 | |
| 31 // Check if the {receiver} is actually a JSGeneratorObject. | 29 // Check if the {receiver} is actually a JSGeneratorObject. |
| 32 Label if_receiverisincompatible(this, Label::kDeferred); | 30 Label if_receiverisincompatible(this, Label::kDeferred); |
| 33 GotoIf(TaggedIsSmi(receiver), &if_receiverisincompatible); | 31 GotoIf(TaggedIsSmi(receiver), &if_receiverisincompatible); |
| 34 Node* receiver_instance_type = LoadInstanceType(receiver); | 32 Node* receiver_instance_type = LoadInstanceType(receiver); |
| 35 GotoIfNot(Word32Equal(receiver_instance_type, | 33 GotoIfNot(Word32Equal(receiver_instance_type, |
| 36 Int32Constant(JS_GENERATOR_OBJECT_TYPE)), | 34 Int32Constant(JS_GENERATOR_OBJECT_TYPE)), |
| 37 &if_receiverisincompatible); | 35 &if_receiverisincompatible); |
| 38 | 36 |
| 39 // Check if the {receiver} is running or already closed. | 37 // Check if the {receiver} is running or already closed. |
| 40 Node* receiver_continuation = | 38 Node* receiver_continuation = |
| 41 LoadObjectField(receiver, JSGeneratorObject::kContinuationOffset); | 39 LoadObjectField(receiver, JSGeneratorObject::kContinuationOffset); |
| 42 Label if_receiverisclosed(this, Label::kDeferred), | 40 Label if_receiverisclosed(this, Label::kDeferred), |
| 43 if_receiverisrunning(this, Label::kDeferred); | 41 if_receiverisrunning(this, Label::kDeferred); |
| 42 Node* closed = SmiConstant(JSGeneratorObject::kGeneratorClosed); |
| 44 GotoIf(SmiEqual(receiver_continuation, closed), &if_receiverisclosed); | 43 GotoIf(SmiEqual(receiver_continuation, closed), &if_receiverisclosed); |
| 45 DCHECK_LT(JSGeneratorObject::kGeneratorExecuting, | 44 DCHECK_LT(JSGeneratorObject::kGeneratorExecuting, |
| 46 JSGeneratorObject::kGeneratorClosed); | 45 JSGeneratorObject::kGeneratorClosed); |
| 47 GotoIf(SmiLessThan(receiver_continuation, closed), &if_receiverisrunning); | 46 GotoIf(SmiLessThan(receiver_continuation, closed), &if_receiverisrunning); |
| 48 | 47 |
| 49 // Resume the {receiver} using our trampoline. | 48 // Resume the {receiver} using our trampoline. |
| 50 VARIABLE(var_exception, MachineRepresentation::kTagged, UndefinedConstant()); | 49 VARIABLE(var_exception, MachineRepresentation::kTagged, UndefinedConstant()); |
| 51 Label if_exception(this, Label::kDeferred), if_final_return(this); | 50 Label if_exception(this, Label::kDeferred), if_final_return(this); |
| 52 Node* result = | 51 Node* result = |
| 53 CallStub(CodeFactory::ResumeGenerator(isolate()), context, value, | 52 CallStub(CodeFactory::ResumeGenerator(isolate()), context, value, |
| 54 receiver, SmiConstant(resume_mode), | 53 receiver, SmiConstant(resume_mode), |
| 55 SmiConstant(static_cast<int>(SuspendFlags::kGeneratorYield))); | 54 SmiConstant(static_cast<int>(SuspendFlags::kGeneratorYield))); |
| 56 // Make sure we close the generator if there was an exception. | 55 // Make sure we close the generator if there was an exception. |
| 57 GotoIfException(result, &if_exception, &var_exception); | 56 GotoIfException(result, &if_exception, &var_exception); |
| 58 | 57 |
| 59 // If the generator is not suspended (i.e., it's state is 'closed'), | 58 // If the generator is not suspended (i.e., its state is 'executing'), |
| 60 // wrap the return value in IteratorResult. | 59 // close it and wrap the return value in IteratorResult. |
| 61 Node* result_continuation = | 60 Node* result_continuation = |
| 62 LoadObjectField(receiver, JSGeneratorObject::kContinuationOffset); | 61 LoadObjectField(receiver, JSGeneratorObject::kContinuationOffset); |
| 63 GotoIf(SmiEqual(result_continuation, closed), &if_final_return); | 62 |
| 63 // The generator function should not close the generator by itself, let's |
| 64 // check it is indeed not closed yet. |
| 65 CSA_ASSERT(this, SmiNotEqual(result_continuation, closed)); |
| 66 |
| 67 Node* executing = SmiConstant(JSGeneratorObject::kGeneratorExecuting); |
| 68 GotoIf(SmiEqual(result_continuation, executing), &if_final_return); |
| 69 |
| 64 Return(result); | 70 Return(result); |
| 65 | 71 |
| 66 Callable create_iter_result_object = | 72 Callable create_iter_result_object = |
| 67 Builtins::CallableFor(isolate(), Builtins::kCreateIterResultObject); | 73 Builtins::CallableFor(isolate(), Builtins::kCreateIterResultObject); |
| 68 | |
| 69 BIND(&if_final_return); | 74 BIND(&if_final_return); |
| 70 { | 75 { |
| 76 // Close the generator. |
| 77 StoreObjectFieldNoWriteBarrier( |
| 78 receiver, JSGeneratorObject::kContinuationOffset, closed); |
| 71 // Return the wrapped result. | 79 // Return the wrapped result. |
| 72 Return( | 80 Return( |
| 73 CallStub(create_iter_result_object, context, result, TrueConstant())); | 81 CallStub(create_iter_result_object, context, result, TrueConstant())); |
| 74 } | 82 } |
| 75 | 83 |
| 76 BIND(&if_receiverisincompatible); | 84 BIND(&if_receiverisincompatible); |
| 77 { | 85 { |
| 78 // The {receiver} is not a valid JSGeneratorObject. | 86 // The {receiver} is not a valid JSGeneratorObject. |
| 79 CallRuntime(Runtime::kThrowIncompatibleMethodReceiver, context, | 87 CallRuntime(Runtime::kThrowIncompatibleMethodReceiver, context, |
| 80 HeapConstant( | 88 HeapConstant( |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 141 Node* receiver = Parameter(Descriptor::kReceiver); | 149 Node* receiver = Parameter(Descriptor::kReceiver); |
| 142 Node* exception = Parameter(Descriptor::kException); | 150 Node* exception = Parameter(Descriptor::kException); |
| 143 Node* context = Parameter(Descriptor::kContext); | 151 Node* context = Parameter(Descriptor::kContext); |
| 144 GeneratorPrototypeResume(receiver, exception, context, | 152 GeneratorPrototypeResume(receiver, exception, context, |
| 145 JSGeneratorObject::kThrow, | 153 JSGeneratorObject::kThrow, |
| 146 "[Generator].prototype.throw"); | 154 "[Generator].prototype.throw"); |
| 147 } | 155 } |
| 148 | 156 |
| 149 } // namespace internal | 157 } // namespace internal |
| 150 } // namespace v8 | 158 } // namespace v8 |
| OLD | NEW |