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 | 7 |
8 #include "src/code-factory.h" | |
8 #include "src/promise-utils.h" | 9 #include "src/promise-utils.h" |
9 | 10 |
10 namespace v8 { | 11 namespace v8 { |
11 namespace internal { | 12 namespace internal { |
12 | 13 |
13 // ES#sec-promise-resolve-functions | 14 // ES#sec-promise-resolve-functions |
14 // Promise Resolve Functions | 15 // Promise Resolve Functions |
15 BUILTIN(PromiseResolveClosure) { | 16 BUILTIN(PromiseResolveClosure) { |
16 HandleScope scope(isolate); | 17 HandleScope scope(isolate); |
17 | 18 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
73 &resolve, &reject); | 74 &resolve, &reject); |
74 | 75 |
75 Handle<FixedArray> result = isolate->factory()->NewFixedArray(2); | 76 Handle<FixedArray> result = isolate->factory()->NewFixedArray(2); |
76 result->set(0, *resolve); | 77 result->set(0, *resolve); |
77 result->set(1, *reject); | 78 result->set(1, *reject); |
78 | 79 |
79 return *isolate->factory()->NewJSArrayWithElements(result, FAST_ELEMENTS, 2, | 80 return *isolate->factory()->NewJSArrayWithElements(result, FAST_ELEMENTS, 2, |
80 NOT_TENURED); | 81 NOT_TENURED); |
81 } | 82 } |
82 | 83 |
84 void Builtins::Generate_PromiseConstructor( | |
85 compiler::CodeAssemblerState* state) { | |
86 CodeStubAssembler a(state); | |
87 typedef CodeStubAssembler::Variable Variable; | |
88 typedef CodeStubAssembler::Label Label; | |
89 typedef compiler::Node Node; | |
90 | |
91 Node* const executor = a.Parameter(1); | |
92 Node* const new_target = a.Parameter(2); | |
93 Node* const context = a.Parameter(4); | |
94 Isolate* isolate = a.isolate(); | |
95 | |
96 Label if_targetisundefined(&a, Label::kDeferred); | |
97 | |
98 a.GotoIf(a.WordEqual(new_target, a.UndefinedConstant()), | |
99 &if_targetisundefined); | |
100 | |
101 Label if_notcallable(&a, Label::kDeferred), | |
102 if_rejectpromise(&a, Label::kDeferred); | |
jgruber
2016/11/22 08:55:55
if_rejectpromise could be moved into the run_execu
gsathya
2016/11/23 14:31:18
Done.
| |
103 | |
104 a.GotoIf(a.TaggedIsSmi(executor), &if_notcallable); | |
105 | |
106 Node* const executor_map = a.LoadMap(executor); | |
107 a.GotoUnless(a.IsCallableMap(executor_map), &if_notcallable); | |
108 | |
109 Node* const native_context = a.LoadNativeContext(context); | |
110 Node* const promise_fun = | |
111 a.LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX); | |
112 | |
113 Label if_targetisnotmodified(&a), if_targetismodified(&a, Label::kDeferred), | |
114 run_executor(&a), out(&a), debug_push(&a, Label::kDeferred), | |
115 debug_pop(&a, Label::kDeferred); | |
116 a.Branch(a.WordEqual(promise_fun, new_target), &if_targetisnotmodified, | |
117 &if_targetismodified); | |
118 | |
119 Variable var_result(&a, MachineRepresentation::kTagged), | |
120 var_reject_call(&a, MachineRepresentation::kTagged), | |
121 var_reason(&a, MachineRepresentation::kTagged); | |
122 | |
123 a.Bind(&if_targetisnotmodified); | |
124 { | |
125 Node* const initial_map = a.LoadObjectField( | |
126 promise_fun, JSFunction::kPrototypeOrInitialMapOffset); | |
127 | |
128 Node* const instance = a.AllocateJSObjectFromMap(initial_map); | |
129 var_result.Bind(instance); | |
130 a.Branch(a.IsDebugActive(), &debug_push, &run_executor); | |
131 } | |
132 | |
133 a.Bind(&if_targetismodified); | |
134 { | |
135 Node* const instance = | |
136 a.CallRuntime(Runtime::kNewObject, context, promise_fun, new_target); | |
jgruber
2016/11/22 08:55:55
Just curious, why is it not possible to call a.All
gsathya
2016/11/23 14:31:18
The subclass setup seemed more involved and I wasn
| |
137 | |
138 var_result.Bind(instance); | |
139 a.Branch(a.IsDebugActive(), &debug_push, &run_executor); | |
140 } | |
141 | |
142 a.Bind(&debug_push); | |
143 { | |
144 a.CallRuntime(Runtime::kDebugPushPromise, context, var_result.value()); | |
145 a.Goto(&run_executor); | |
146 } | |
147 | |
148 a.Bind(&run_executor); | |
149 { | |
150 Node* const key = | |
151 a.HeapConstant(a.isolate()->factory()->promise_state_symbol()); | |
152 Node* const value = a.SmiConstant(Smi::FromInt(kPromisePending)); | |
153 Node* const language_mode = a.SmiConstant(Smi::FromInt(STRICT)); | |
154 a.CallRuntime(Runtime::kSetProperty, context, var_result.value(), key, | |
155 value, language_mode); | |
156 Node* const resolving_functions = a.CallRuntime( | |
157 Runtime::kCreateResolvingFunctions, context, var_result.value()); | |
158 Node* const resolve = | |
159 a.LoadFixedArrayElement(resolving_functions, a.IntPtrConstant(0)); | |
160 Node* const reject = | |
161 a.LoadFixedArrayElement(resolving_functions, a.IntPtrConstant(1)); | |
162 var_reject_call.Bind(reject); | |
jgruber
2016/11/22 08:55:55
Seems like you can just use the Node* reject varia
gsathya
2016/11/23 14:31:18
Done.
| |
163 Callable call_callable = CodeFactory::Call(isolate); | |
164 | |
165 Node* const maybe_exception = | |
166 a.CallJS(call_callable, context, executor, a.UndefinedConstant(), | |
167 resolve, reject); | |
168 | |
169 a.GotoIfException(maybe_exception, &if_rejectpromise, &var_reason); | |
170 a.Branch(a.IsDebugActive(), &debug_pop, &out); | |
171 } | |
172 | |
173 a.Bind(&if_rejectpromise); | |
174 { | |
175 Callable call_callable = CodeFactory::Call(isolate); | |
176 a.CallJS(call_callable, context, var_reject_call.value(), | |
177 a.UndefinedConstant(), var_reason.value()); | |
178 a.Branch(a.IsDebugActive(), &debug_pop, &out); | |
179 } | |
180 | |
181 a.Bind(&debug_pop); | |
182 { | |
183 a.CallRuntime(Runtime::kDebugPopPromise, context); | |
184 a.Goto(&out); | |
185 } | |
186 | |
187 a.Bind(&out); | |
188 a.Return(var_result.value()); | |
189 | |
190 // 1. If NewTarget is undefined, throw a TypeError exception. | |
191 a.Bind(&if_targetisundefined); | |
192 { | |
193 Node* const message_id = | |
194 a.SmiConstant(Smi::FromInt(MessageTemplate::kNotAPromise)); | |
jgruber
2016/11/22 08:55:55
Here and elsewhere: since recently you can just ca
gsathya
2016/11/23 14:31:18
Done.
| |
195 a.CallRuntime(Runtime::kThrowTypeError, context, message_id, new_target); | |
196 // a.ToString(a, new_target)); | |
jgruber
2016/11/22 08:55:55
Please remove comment.
gsathya
2016/11/23 14:31:18
Done.
| |
197 a.Return(a.UndefinedConstant()); // Never reached. | |
198 } | |
199 | |
200 // 2. If IsCallable(executor) is false, throw a TypeError exception. | |
201 a.Bind(&if_notcallable); | |
202 { | |
203 Node* const message_id = | |
204 a.SmiConstant(Smi::FromInt(MessageTemplate::kResolverNotAFunction)); | |
205 a.CallRuntime(Runtime::kThrowTypeError, context, message_id, executor); | |
206 a.Return(a.UndefinedConstant()); // Never reached. | |
207 } | |
208 } | |
209 | |
210 void Builtins::Generate_PromiseInternalConstructor( | |
211 compiler::CodeAssemblerState* state) { | |
212 typedef compiler::Node Node; | |
213 CodeStubAssembler a(state); | |
214 | |
215 Node* const context = a.Parameter(3); | |
216 Node* const native_context = a.LoadNativeContext(context); | |
217 Node* const promise_fun = | |
218 a.LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX); | |
219 Node* const initial_map = | |
220 a.LoadObjectField(promise_fun, JSFunction::kPrototypeOrInitialMapOffset); | |
221 Node* const instance = a.AllocateJSObjectFromMap(initial_map); | |
222 a.Return(instance); | |
223 } | |
224 | |
225 // TODO(gsathya): Refactor promise.js::IsPromise to use this. | |
226 void Builtins::Generate_IsPromise(compiler::CodeAssemblerState* state) { | |
227 CodeStubAssembler a(state); | |
228 typedef compiler::Node Node; | |
229 typedef CodeStubAssembler::Label Label; | |
230 | |
231 Node* const maybe_promise = a.Parameter(1); | |
232 Label if_ispromise(&a), if_isnotpromise(&a, Label::kDeferred); | |
233 a.GotoIf(a.TaggedIsSmi(maybe_promise), &if_isnotpromise); | |
234 | |
235 Node* const maybe_promise_type = | |
236 a.LoadMapInstanceType(a.LoadMap(maybe_promise)); | |
237 | |
238 a.Branch(a.Word32Equal(maybe_promise_type, a.Int32Constant(JS_PROMISE_TYPE)), | |
239 &if_ispromise, &if_isnotpromise); | |
240 | |
241 a.Bind(&if_ispromise); | |
242 a.Return(a.BooleanConstant(true)); | |
243 | |
244 a.Bind(&if_isnotpromise); | |
245 a.Return(a.BooleanConstant(false)); | |
246 } | |
247 | |
83 } // namespace internal | 248 } // namespace internal |
84 } // namespace v8 | 249 } // namespace v8 |
OLD | NEW |