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.h" | 5 #include "src/builtins/builtins-utils.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 | 9 |
10 namespace v8 { | 10 namespace v8 { |
11 namespace internal { | 11 namespace internal { |
12 | 12 |
13 namespace { | 13 typedef compiler::CodeAssemblerState CodeAssemblerState; |
14 | 14 |
15 void Generate_GeneratorPrototypeResume( | 15 class GeneratorBuiltinsAssembler : public CodeStubAssembler { |
16 CodeStubAssembler* assembler, JSGeneratorObject::ResumeMode resume_mode, | 16 public: |
17 char const* const method_name) { | 17 explicit GeneratorBuiltinsAssembler(CodeAssemblerState* state) |
18 typedef CodeStubAssembler::Label Label; | 18 : CodeStubAssembler(state) {} |
19 typedef compiler::Node Node; | |
20 | 19 |
21 Node* receiver = assembler->Parameter(0); | 20 protected: |
22 Node* value = assembler->Parameter(1); | 21 void GeneratorPrototypeResume(JSGeneratorObject::ResumeMode resume_mode, |
23 Node* context = assembler->Parameter(4); | 22 char const* const method_name); |
24 Node* closed = | 23 }; |
25 assembler->SmiConstant(Smi::FromInt(JSGeneratorObject::kGeneratorClosed)); | 24 |
| 25 void GeneratorBuiltinsAssembler::GeneratorPrototypeResume( |
| 26 JSGeneratorObject::ResumeMode resume_mode, char const* const method_name) { |
| 27 Node* receiver = Parameter(0); |
| 28 Node* value = Parameter(1); |
| 29 Node* context = Parameter(4); |
| 30 Node* closed = SmiConstant(JSGeneratorObject::kGeneratorClosed); |
26 | 31 |
27 // Check if the {receiver} is actually a JSGeneratorObject. | 32 // Check if the {receiver} is actually a JSGeneratorObject. |
28 Label if_receiverisincompatible(assembler, Label::kDeferred); | 33 Label if_receiverisincompatible(this, Label::kDeferred); |
29 assembler->GotoIf(assembler->TaggedIsSmi(receiver), | 34 GotoIf(TaggedIsSmi(receiver), &if_receiverisincompatible); |
30 &if_receiverisincompatible); | 35 Node* receiver_instance_type = LoadInstanceType(receiver); |
31 Node* receiver_instance_type = assembler->LoadInstanceType(receiver); | 36 GotoUnless(Word32Equal(receiver_instance_type, |
32 assembler->GotoUnless(assembler->Word32Equal( | 37 Int32Constant(JS_GENERATOR_OBJECT_TYPE)), |
33 receiver_instance_type, | 38 &if_receiverisincompatible); |
34 assembler->Int32Constant(JS_GENERATOR_OBJECT_TYPE)), | |
35 &if_receiverisincompatible); | |
36 | 39 |
37 // Check if the {receiver} is running or already closed. | 40 // Check if the {receiver} is running or already closed. |
38 Node* receiver_continuation = assembler->LoadObjectField( | 41 Node* receiver_continuation = |
39 receiver, JSGeneratorObject::kContinuationOffset); | 42 LoadObjectField(receiver, JSGeneratorObject::kContinuationOffset); |
40 Label if_receiverisclosed(assembler, Label::kDeferred), | 43 Label if_receiverisclosed(this, Label::kDeferred), |
41 if_receiverisrunning(assembler, Label::kDeferred); | 44 if_receiverisrunning(this, Label::kDeferred); |
42 assembler->GotoIf(assembler->SmiEqual(receiver_continuation, closed), | 45 GotoIf(SmiEqual(receiver_continuation, closed), &if_receiverisclosed); |
43 &if_receiverisclosed); | |
44 DCHECK_LT(JSGeneratorObject::kGeneratorExecuting, | 46 DCHECK_LT(JSGeneratorObject::kGeneratorExecuting, |
45 JSGeneratorObject::kGeneratorClosed); | 47 JSGeneratorObject::kGeneratorClosed); |
46 assembler->GotoIf(assembler->SmiLessThan(receiver_continuation, closed), | 48 GotoIf(SmiLessThan(receiver_continuation, closed), &if_receiverisrunning); |
47 &if_receiverisrunning); | |
48 | 49 |
49 // Resume the {receiver} using our trampoline. | 50 // Resume the {receiver} using our trampoline. |
50 Node* result = assembler->CallStub( | 51 Node* result = CallStub(CodeFactory::ResumeGenerator(isolate()), context, |
51 CodeFactory::ResumeGenerator(assembler->isolate()), context, value, | 52 value, receiver, SmiConstant(resume_mode)); |
52 receiver, assembler->SmiConstant(Smi::FromInt(resume_mode))); | 53 Return(result); |
53 assembler->Return(result); | |
54 | 54 |
55 assembler->Bind(&if_receiverisincompatible); | 55 Bind(&if_receiverisincompatible); |
56 { | 56 { |
57 // The {receiver} is not a valid JSGeneratorObject. | 57 // The {receiver} is not a valid JSGeneratorObject. |
58 Node* result = assembler->CallRuntime( | 58 Node* result = |
59 Runtime::kThrowIncompatibleMethodReceiver, context, | 59 CallRuntime(Runtime::kThrowIncompatibleMethodReceiver, context, |
60 assembler->HeapConstant(assembler->factory()->NewStringFromAsciiChecked( | 60 HeapConstant(factory()->NewStringFromAsciiChecked( |
61 method_name, TENURED)), | 61 method_name, TENURED)), |
62 receiver); | 62 receiver); |
63 assembler->Return(result); // Never reached. | 63 Return(result); // Never reached. |
64 } | 64 } |
65 | 65 |
66 assembler->Bind(&if_receiverisclosed); | 66 Bind(&if_receiverisclosed); |
67 { | 67 { |
68 Callable create_iter_result_object = | 68 Callable create_iter_result_object = |
69 CodeFactory::CreateIterResultObject(assembler->isolate()); | 69 CodeFactory::CreateIterResultObject(isolate()); |
70 | 70 |
71 // The {receiver} is closed already. | 71 // The {receiver} is closed already. |
72 Node* result = nullptr; | 72 Node* result = nullptr; |
73 switch (resume_mode) { | 73 switch (resume_mode) { |
74 case JSGeneratorObject::kNext: | 74 case JSGeneratorObject::kNext: |
75 result = assembler->CallStub(create_iter_result_object, context, | 75 result = CallStub(create_iter_result_object, context, |
76 assembler->UndefinedConstant(), | 76 UndefinedConstant(), TrueConstant()); |
77 assembler->TrueConstant()); | |
78 break; | 77 break; |
79 case JSGeneratorObject::kReturn: | 78 case JSGeneratorObject::kReturn: |
80 result = assembler->CallStub(create_iter_result_object, context, value, | 79 result = |
81 assembler->TrueConstant()); | 80 CallStub(create_iter_result_object, context, value, TrueConstant()); |
82 break; | 81 break; |
83 case JSGeneratorObject::kThrow: | 82 case JSGeneratorObject::kThrow: |
84 result = assembler->CallRuntime(Runtime::kThrow, context, value); | 83 result = CallRuntime(Runtime::kThrow, context, value); |
85 break; | 84 break; |
86 } | 85 } |
87 assembler->Return(result); | 86 Return(result); |
88 } | 87 } |
89 | 88 |
90 assembler->Bind(&if_receiverisrunning); | 89 Bind(&if_receiverisrunning); |
91 { | 90 { |
92 Node* result = | 91 Node* result = CallRuntime(Runtime::kThrowGeneratorRunning, context); |
93 assembler->CallRuntime(Runtime::kThrowGeneratorRunning, context); | 92 Return(result); // Never reached. |
94 assembler->Return(result); // Never reached. | |
95 } | 93 } |
96 } | 94 } |
97 | 95 |
98 } // anonymous namespace | |
99 | |
100 // ES6 section 25.3.1.2 Generator.prototype.next ( value ) | 96 // ES6 section 25.3.1.2 Generator.prototype.next ( value ) |
101 void Builtins::Generate_GeneratorPrototypeNext( | 97 TF_BUILTIN(GeneratorPrototypeNext, GeneratorBuiltinsAssembler) { |
102 compiler::CodeAssemblerState* state) { | 98 GeneratorPrototypeResume(JSGeneratorObject::kNext, |
103 CodeStubAssembler assembler(state); | 99 "[Generator].prototype.next"); |
104 Generate_GeneratorPrototypeResume(&assembler, JSGeneratorObject::kNext, | |
105 "[Generator].prototype.next"); | |
106 } | 100 } |
107 | 101 |
108 // ES6 section 25.3.1.3 Generator.prototype.return ( value ) | 102 // ES6 section 25.3.1.3 Generator.prototype.return ( value ) |
109 void Builtins::Generate_GeneratorPrototypeReturn( | 103 TF_BUILTIN(GeneratorPrototypeReturn, GeneratorBuiltinsAssembler) { |
110 compiler::CodeAssemblerState* state) { | 104 GeneratorPrototypeResume(JSGeneratorObject::kReturn, |
111 CodeStubAssembler assembler(state); | 105 "[Generator].prototype.return"); |
112 Generate_GeneratorPrototypeResume(&assembler, JSGeneratorObject::kReturn, | |
113 "[Generator].prototype.return"); | |
114 } | 106 } |
115 | 107 |
116 // ES6 section 25.3.1.4 Generator.prototype.throw ( exception ) | 108 // ES6 section 25.3.1.4 Generator.prototype.throw ( exception ) |
117 void Builtins::Generate_GeneratorPrototypeThrow( | 109 TF_BUILTIN(GeneratorPrototypeThrow, GeneratorBuiltinsAssembler) { |
118 compiler::CodeAssemblerState* state) { | 110 GeneratorPrototypeResume(JSGeneratorObject::kThrow, |
119 CodeStubAssembler assembler(state); | 111 "[Generator].prototype.throw"); |
120 Generate_GeneratorPrototypeResume(&assembler, JSGeneratorObject::kThrow, | |
121 "[Generator].prototype.throw"); | |
122 } | 112 } |
123 | 113 |
124 } // namespace internal | 114 } // namespace internal |
125 } // namespace v8 | 115 } // namespace v8 |
OLD | NEW |