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 | |
103 a.GotoIf(a.TaggedIsSmi(executor), &if_notcallable); | |
104 | |
105 Node* const executor_map = a.LoadMap(executor); | |
106 a.GotoUnless(a.IsCallableMap(executor_map), &if_notcallable); | |
107 | |
108 Node* const native_context = a.LoadNativeContext(context); | |
109 Node* const promise_fun = | |
110 a.LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX); | |
111 | |
112 Label if_targetisnotmodified(&a), if_targetismodified(&a, Label::kDeferred), | |
113 run_executor(&a), debug_push(&a, Label::kDeferred); | |
114 a.Branch(a.WordEqual(promise_fun, new_target), &if_targetisnotmodified, | |
115 &if_targetismodified); | |
116 | |
117 Variable var_result(&a, MachineRepresentation::kTagged), | |
118 var_reject_call(&a, MachineRepresentation::kTagged), | |
119 var_reason(&a, MachineRepresentation::kTagged); | |
120 | |
121 a.Bind(&if_targetisnotmodified); | |
122 { | |
123 Node* const initial_map = a.LoadObjectField( | |
124 promise_fun, JSFunction::kPrototypeOrInitialMapOffset); | |
125 | |
126 Node* const instance = a.AllocateJSObjectFromMap(initial_map); | |
127 var_result.Bind(instance); | |
128 a.Branch(a.IsDebugActive(), &debug_push, &run_executor); | |
129 } | |
130 | |
131 a.Bind(&if_targetismodified); | |
132 { | |
133 Callable fast_new_object_stub = CodeFactory::FastNewObject(isolate); | |
jgruber
2016/11/24 07:42:30
Perhaps Benedikt can chime in whether the usage of
| |
134 Node* const instance = | |
135 a.CallStub(fast_new_object_stub, context, promise_fun, new_target); | |
136 | |
137 var_result.Bind(instance); | |
138 a.Branch(a.IsDebugActive(), &debug_push, &run_executor); | |
139 } | |
140 | |
141 a.Bind(&debug_push); | |
142 { | |
143 a.CallRuntime(Runtime::kDebugPushPromise, context, var_result.value()); | |
144 a.Goto(&run_executor); | |
145 } | |
146 | |
147 a.Bind(&run_executor); | |
148 { | |
149 Label out(&a), if_rejectpromise(&a), debug_pop(&a, Label::kDeferred); | |
150 | |
151 Node* const key = | |
152 a.HeapConstant(a.isolate()->factory()->promise_state_symbol()); | |
153 Node* const value = a.SmiConstant(kPromisePending); | |
154 Node* const language_mode = a.SmiConstant(STRICT); | |
155 a.CallRuntime(Runtime::kSetProperty, context, var_result.value(), key, | |
156 value, language_mode); | |
157 Node* const resolving_functions = a.CallRuntime( | |
158 Runtime::kCreateResolvingFunctions, context, var_result.value()); | |
159 Node* const resolve = | |
160 a.LoadFixedArrayElement(resolving_functions, a.IntPtrConstant(0)); | |
161 Node* const reject = | |
162 a.LoadFixedArrayElement(resolving_functions, a.IntPtrConstant(1)); | |
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 a.Bind(&if_rejectpromise); | |
173 { | |
174 Callable call_callable = CodeFactory::Call(isolate); | |
175 a.CallJS(call_callable, context, reject, a.UndefinedConstant(), | |
176 var_reason.value()); | |
177 a.Branch(a.IsDebugActive(), &debug_pop, &out); | |
178 } | |
179 | |
180 a.Bind(&debug_pop); | |
181 { | |
182 a.CallRuntime(Runtime::kDebugPopPromise, context); | |
183 a.Goto(&out); | |
184 } | |
185 a.Bind(&out); | |
186 a.Return(var_result.value()); | |
187 } | |
188 | |
189 // 1. If NewTarget is undefined, throw a TypeError exception. | |
190 a.Bind(&if_targetisundefined); | |
191 { | |
192 Node* const message_id = a.SmiConstant(MessageTemplate::kNotAPromise); | |
193 a.CallRuntime(Runtime::kThrowTypeError, context, message_id, new_target); | |
194 a.Return(a.UndefinedConstant()); // Never reached. | |
195 } | |
196 | |
197 // 2. If IsCallable(executor) is false, throw a TypeError exception. | |
198 a.Bind(&if_notcallable); | |
199 { | |
200 Node* const message_id = | |
201 a.SmiConstant(MessageTemplate::kResolverNotAFunction); | |
202 a.CallRuntime(Runtime::kThrowTypeError, context, message_id, executor); | |
203 a.Return(a.UndefinedConstant()); // Never reached. | |
204 } | |
205 } | |
206 | |
207 void Builtins::Generate_PromiseInternalConstructor( | |
208 compiler::CodeAssemblerState* state) { | |
209 typedef compiler::Node Node; | |
210 CodeStubAssembler a(state); | |
211 | |
212 Node* const context = a.Parameter(3); | |
213 Node* const native_context = a.LoadNativeContext(context); | |
214 Node* const promise_fun = | |
215 a.LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX); | |
216 Node* const initial_map = | |
217 a.LoadObjectField(promise_fun, JSFunction::kPrototypeOrInitialMapOffset); | |
218 Node* const instance = a.AllocateJSObjectFromMap(initial_map); | |
219 a.Return(instance); | |
220 } | |
221 | |
222 // TODO(gsathya): Refactor promise.js::IsPromise to use this. | |
223 void Builtins::Generate_IsPromise(compiler::CodeAssemblerState* state) { | |
224 CodeStubAssembler a(state); | |
225 typedef compiler::Node Node; | |
226 typedef CodeStubAssembler::Label Label; | |
227 | |
228 Node* const maybe_promise = a.Parameter(1); | |
229 Label if_ispromise(&a), if_isnotpromise(&a, Label::kDeferred); | |
230 a.GotoIf(a.TaggedIsSmi(maybe_promise), &if_isnotpromise); | |
231 | |
232 Node* const maybe_promise_type = | |
233 a.LoadMapInstanceType(a.LoadMap(maybe_promise)); | |
234 | |
235 a.Branch(a.Word32Equal(maybe_promise_type, a.Int32Constant(JS_PROMISE_TYPE)), | |
236 &if_ispromise, &if_isnotpromise); | |
237 | |
238 a.Bind(&if_ispromise); | |
239 a.Return(a.BooleanConstant(true)); | |
240 | |
241 a.Bind(&if_isnotpromise); | |
242 a.Return(a.BooleanConstant(false)); | |
243 } | |
244 | |
83 } // namespace internal | 245 } // namespace internal |
84 } // namespace v8 | 246 } // namespace v8 |
OLD | NEW |