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

Side by Side Diff: src/builtins/builtins-promise.cc

Issue 2583753002: [promises] Use TF_BUILTIN (Closed)
Patch Set: rebase Created 4 years 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 #include "src/promise-utils.h" 9 #include "src/promise-utils.h"
10 10
11 namespace v8 { 11 namespace v8 {
12 namespace internal { 12 namespace internal {
13 13
14 // ES#sec-promise-reject-functions 14 typedef compiler::Node Node;
15 // Promise Reject Functions 15 typedef CodeStubAssembler::ParameterMode ParameterMode;
16 BUILTIN(PromiseRejectClosure) { 16 typedef compiler::CodeAssemblerState CodeAssemblerState;
17 HandleScope scope(isolate);
18 17
19 Handle<Context> context(isolate->context(), isolate); 18 class PromiseBuiltinsAssembler : public CodeStubAssembler {
19 public:
20 explicit PromiseBuiltinsAssembler(CodeAssemblerState* state)
21 : CodeStubAssembler(state) {}
20 22
21 if (PromiseUtils::HasAlreadyVisited(context)) { 23 protected:
22 return isolate->heap()->undefined_value(); 24 Node* ThrowIfNotJSReceiver(Node* context, Node* value,
25 MessageTemplate::Template msg_template);
26
27 Node* SpeciesConstructor(Node* context, Node* object,
28 Node* default_constructor);
29
30 Node* PromiseHasHandler(Node* promise);
31
32 void PromiseSetHasHandler(Node* promise);
33
34 void AppendPromiseCallback(int offset, compiler::Node* promise,
35 compiler::Node* value);
36
37 Node* InternalPerformPromiseThen(Node* context, Node* promise,
38 Node* on_resolve, Node* on_reject,
39 Node* deferred);
40
41 void InternalResolvePromise(Node* context, Node* promise, Node* result,
42 Label* out);
43
44 void BranchIfFastPath(Node* context, Node* promise, Label* if_isunmodified,
45 Label* if_ismodified);
46 };
47
48 Node* PromiseBuiltinsAssembler::ThrowIfNotJSReceiver(
49 Node* context, Node* value, MessageTemplate::Template msg_template) {
50 Label out(this), throw_exception(this, Label::kDeferred);
51 Variable var_value_map(this, MachineRepresentation::kTagged);
52
53 GotoIf(TaggedIsSmi(value), &throw_exception);
54
55 // Load the instance type of the {value}.
56 var_value_map.Bind(LoadMap(value));
57 Node* const value_instance_type = LoadMapInstanceType(var_value_map.value());
58
59 Branch(IsJSReceiverInstanceType(value_instance_type), &out, &throw_exception);
60
61 // The {value} is not a compatible receiver for this method.
62 Bind(&throw_exception);
63 {
64 Node* const message_id = SmiConstant(msg_template);
65 CallRuntime(Runtime::kThrowTypeError, context, message_id);
66 var_value_map.Bind(UndefinedConstant());
67 Goto(&out); // Never reached.
23 } 68 }
24 69
25 PromiseUtils::SetAlreadyVisited(context); 70 Bind(&out);
26 Handle<Object> value = args.atOrUndefined(isolate, 1);
27 Handle<JSObject> promise = handle(PromiseUtils::GetPromise(context), isolate);
28 Handle<Object> debug_event =
29 handle(PromiseUtils::GetDebugEvent(context), isolate);
30 MaybeHandle<Object> maybe_result;
31 Handle<Object> argv[] = {promise, value, debug_event};
32 RETURN_FAILURE_ON_EXCEPTION(
33 isolate, Execution::Call(isolate, isolate->promise_internal_reject(),
34 isolate->factory()->undefined_value(),
35 arraysize(argv), argv));
36 return isolate->heap()->undefined_value();
37 }
38
39 // ES#sec-createresolvingfunctions
40 // CreateResolvingFunctions ( promise )
41 BUILTIN(CreateResolvingFunctions) {
42 HandleScope scope(isolate);
43 DCHECK_EQ(3, args.length());
44
45 Handle<JSObject> promise = args.at<JSObject>(1);
46 Handle<Object> debug_event = args.at(2);
47 Handle<JSFunction> resolve, reject;
48
49 PromiseUtils::CreateResolvingFunctions(isolate, promise, debug_event,
50 &resolve, &reject);
51
52 Handle<FixedArray> result = isolate->factory()->NewFixedArray(2);
53 result->set(0, *resolve);
54 result->set(1, *reject);
55
56 return *isolate->factory()->NewJSArrayWithElements(result, FAST_ELEMENTS, 2,
57 NOT_TENURED);
58 }
59
60 void Builtins::Generate_PromiseConstructor(
61 compiler::CodeAssemblerState* state) {
62 CodeStubAssembler a(state);
63 typedef CodeStubAssembler::Variable Variable;
64 typedef CodeStubAssembler::Label Label;
65 typedef compiler::Node Node;
66
67 Node* const executor = a.Parameter(1);
68 Node* const new_target = a.Parameter(2);
69 Node* const context = a.Parameter(4);
70 Isolate* isolate = a.isolate();
71
72 Label if_targetisundefined(&a, Label::kDeferred);
73
74 a.GotoIf(a.IsUndefined(new_target), &if_targetisundefined);
75
76 Label if_notcallable(&a, Label::kDeferred);
77
78 a.GotoIf(a.TaggedIsSmi(executor), &if_notcallable);
79
80 Node* const executor_map = a.LoadMap(executor);
81 a.GotoUnless(a.IsCallableMap(executor_map), &if_notcallable);
82
83 Node* const native_context = a.LoadNativeContext(context);
84 Node* const promise_fun =
85 a.LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
86 Node* const is_debug_active = a.IsDebugActive();
87 Label if_targetisnotmodified(&a), if_targetismodified(&a, Label::kDeferred),
88 run_executor(&a), debug_push(&a, Label::kDeferred), init(&a);
89
90 a.Branch(a.WordEqual(promise_fun, new_target), &if_targetisnotmodified,
91 &if_targetismodified);
92
93 Variable var_result(&a, MachineRepresentation::kTagged),
94 var_reject_call(&a, MachineRepresentation::kTagged),
95 var_reason(&a, MachineRepresentation::kTagged);
96
97 a.Bind(&if_targetisnotmodified);
98 {
99 Node* const instance = a.AllocateJSPromise(context);
100 var_result.Bind(instance);
101 a.Goto(&init);
102 }
103
104 a.Bind(&if_targetismodified);
105 {
106 Callable fast_new_object_stub = CodeFactory::FastNewObject(isolate);
107 Node* const instance =
108 a.CallStub(fast_new_object_stub, context, promise_fun, new_target);
109
110 var_result.Bind(instance);
111 a.Goto(&init);
112 }
113
114 a.Bind(&init);
115 {
116 a.PromiseInit(var_result.value());
117 a.Branch(is_debug_active, &debug_push, &run_executor);
118 }
119
120 a.Bind(&debug_push);
121 {
122 a.CallRuntime(Runtime::kDebugPushPromise, context, var_result.value());
123 a.Goto(&run_executor);
124 }
125
126 a.Bind(&run_executor);
127 {
128 Label out(&a), if_rejectpromise(&a), debug_pop(&a, Label::kDeferred);
129
130 // TODO(gsathya): Move this to TF.
131 Node* const resolving_functions = a.CallRuntime(
132 Runtime::kCreateResolvingFunctions, context, var_result.value());
133 Node* const resolve =
134 a.LoadFixedArrayElement(resolving_functions, a.IntPtrConstant(0));
135 Node* const reject =
136 a.LoadFixedArrayElement(resolving_functions, a.IntPtrConstant(1));
137 Callable call_callable = CodeFactory::Call(isolate);
138
139 Node* const maybe_exception =
140 a.CallJS(call_callable, context, executor, a.UndefinedConstant(),
141 resolve, reject);
142
143 a.GotoIfException(maybe_exception, &if_rejectpromise, &var_reason);
144 a.Branch(is_debug_active, &debug_pop, &out);
145
146 a.Bind(&if_rejectpromise);
147 {
148 Callable call_callable = CodeFactory::Call(isolate);
149 a.CallJS(call_callable, context, reject, a.UndefinedConstant(),
150 var_reason.value());
151 a.Branch(is_debug_active, &debug_pop, &out);
152 }
153
154 a.Bind(&debug_pop);
155 {
156 a.CallRuntime(Runtime::kDebugPopPromise, context);
157 a.Goto(&out);
158 }
159 a.Bind(&out);
160 a.Return(var_result.value());
161 }
162
163 // 1. If NewTarget is undefined, throw a TypeError exception.
164 a.Bind(&if_targetisundefined);
165 {
166 Node* const message_id = a.SmiConstant(MessageTemplate::kNotAPromise);
167 a.CallRuntime(Runtime::kThrowTypeError, context, message_id, new_target);
168 a.Return(a.UndefinedConstant()); // Never reached.
169 }
170
171 // 2. If IsCallable(executor) is false, throw a TypeError exception.
172 a.Bind(&if_notcallable);
173 {
174 Node* const message_id =
175 a.SmiConstant(MessageTemplate::kResolverNotAFunction);
176 a.CallRuntime(Runtime::kThrowTypeError, context, message_id, executor);
177 a.Return(a.UndefinedConstant()); // Never reached.
178 }
179 }
180
181 void Builtins::Generate_PromiseInternalConstructor(
182 compiler::CodeAssemblerState* state) {
183 typedef compiler::Node Node;
184 CodeStubAssembler a(state);
185
186 Node* const context = a.Parameter(3);
187 Node* const instance = a.AllocateJSPromise(context);
188 a.PromiseInit(instance);
189 a.Return(instance);
190 }
191
192 void Builtins::Generate_PromiseCreateAndSet(
193 compiler::CodeAssemblerState* state) {
194 typedef compiler::Node Node;
195 CodeStubAssembler a(state);
196
197 Node* const status = a.Parameter(1);
198 Node* const result = a.Parameter(2);
199 Node* const context = a.Parameter(5);
200
201 Node* const instance = a.AllocateJSPromise(context);
202 a.PromiseSet(instance, status, result);
203 a.Return(instance);
204 }
205
206 namespace {
207
208 compiler::Node* ThrowIfNotJSReceiver(CodeStubAssembler* a, Isolate* isolate,
209 compiler::Node* context,
210 compiler::Node* value,
211 MessageTemplate::Template msg_template) {
212 typedef compiler::Node Node;
213 typedef CodeStubAssembler::Label Label;
214 typedef CodeStubAssembler::Variable Variable;
215
216 Label out(a), throw_exception(a, Label::kDeferred);
217 Variable var_value_map(a, MachineRepresentation::kTagged);
218
219 a->GotoIf(a->TaggedIsSmi(value), &throw_exception);
220
221 // Load the instance type of the {value}.
222 var_value_map.Bind(a->LoadMap(value));
223 Node* const value_instance_type =
224 a->LoadMapInstanceType(var_value_map.value());
225
226 a->Branch(a->IsJSReceiverInstanceType(value_instance_type), &out,
227 &throw_exception);
228
229 // The {value} is not a compatible receiver for this method.
230 a->Bind(&throw_exception);
231 {
232 Node* const message_id = a->SmiConstant(msg_template);
233 a->CallRuntime(Runtime::kThrowTypeError, context, message_id);
234 var_value_map.Bind(a->UndefinedConstant());
235 a->Goto(&out); // Never reached.
236 }
237
238 a->Bind(&out);
239 return var_value_map.value(); 71 return var_value_map.value();
240 } 72 }
241 73
242 } // namespace 74 Node* PromiseBuiltinsAssembler::PromiseHasHandler(Node* promise) {
243 75 Node* const flags = LoadObjectField(promise, JSPromise::kFlagsOffset);
244 void Builtins::Generate_IsPromise(compiler::CodeAssemblerState* state) { 76 return IsSetWord(SmiUntag(flags), 1 << JSPromise::kHasHandlerBit);
245 CodeStubAssembler a(state);
246 typedef compiler::Node Node;
247 typedef CodeStubAssembler::Label Label;
248
249 Node* const maybe_promise = a.Parameter(1);
250 Label if_notpromise(&a, Label::kDeferred);
251
252 a.GotoIf(a.TaggedIsSmi(maybe_promise), &if_notpromise);
253
254 Node* const result = a.SelectBooleanConstant(
255 a.HasInstanceType(maybe_promise, JS_PROMISE_TYPE));
256 a.Return(result);
257
258 a.Bind(&if_notpromise);
259 a.Return(a.FalseConstant());
260 } 77 }
261 78
262 namespace { 79 void PromiseBuiltinsAssembler::PromiseSetHasHandler(Node* promise) {
263 80 Node* const flags =
264 compiler::Node* PromiseHasHandler(CodeStubAssembler* a, 81 SmiUntag(LoadObjectField(promise, JSPromise::kFlagsOffset));
265 compiler::Node* promise) { 82 Node* const new_flags =
266 typedef compiler::Node Node; 83 WordOr(flags, IntPtrConstant(1 << JSPromise::kHasHandlerBit));
267 84 StoreObjectField(promise, JSPromise::kFlagsOffset, SmiTag(new_flags));
268 Node* const flags = a->LoadObjectField(promise, JSPromise::kFlagsOffset);
269 return a->IsSetWord(a->SmiUntag(flags), 1 << JSPromise::kHasHandlerBit);
270 } 85 }
271 86
272 void PromiseSetHasHandler(CodeStubAssembler* a, compiler::Node* promise) { 87 Node* PromiseBuiltinsAssembler::SpeciesConstructor(Node* context, Node* object,
273 typedef compiler::Node Node; 88 Node* default_constructor) {
274 89 Isolate* isolate = this->isolate();
275 Node* const flags = 90 Variable var_result(this, MachineRepresentation::kTagged);
276 a->SmiUntag(a->LoadObjectField(promise, JSPromise::kFlagsOffset));
277 Node* const new_flags =
278 a->WordOr(flags, a->IntPtrConstant(1 << JSPromise::kHasHandlerBit));
279 a->StoreObjectField(promise, JSPromise::kFlagsOffset, a->SmiTag(new_flags));
280 }
281
282 compiler::Node* SpeciesConstructor(CodeStubAssembler* a, Isolate* isolate,
283 compiler::Node* context,
284 compiler::Node* object,
285 compiler::Node* default_constructor) {
286 typedef compiler::Node Node;
287 typedef CodeStubAssembler::Label Label;
288 typedef CodeStubAssembler::Variable Variable;
289
290 Variable var_result(a, MachineRepresentation::kTagged);
291 var_result.Bind(default_constructor); 91 var_result.Bind(default_constructor);
292 92
293 // 2. Let C be ? Get(O, "constructor"). 93 // 2. Let C be ? Get(O, "constructor").
294 Node* const constructor_str = 94 Node* const constructor_str =
295 a->HeapConstant(isolate->factory()->constructor_string()); 95 HeapConstant(isolate->factory()->constructor_string());
296 Callable getproperty_callable = CodeFactory::GetProperty(a->isolate()); 96 Callable getproperty_callable = CodeFactory::GetProperty(isolate);
297 Node* const constructor = 97 Node* const constructor =
298 a->CallStub(getproperty_callable, context, object, constructor_str); 98 CallStub(getproperty_callable, context, object, constructor_str);
299 99
300 // 3. If C is undefined, return defaultConstructor. 100 // 3. If C is undefined, return defaultConstructor.
301 Label out(a); 101 Label out(this);
302 a->GotoIf(a->IsUndefined(constructor), &out); 102 GotoIf(IsUndefined(constructor), &out);
303 103
304 // 4. If Type(C) is not Object, throw a TypeError exception. 104 // 4. If Type(C) is not Object, throw a TypeError exception.
305 ThrowIfNotJSReceiver(a, a->isolate(), context, constructor, 105 ThrowIfNotJSReceiver(context, constructor,
306 MessageTemplate::kConstructorNotReceiver); 106 MessageTemplate::kConstructorNotReceiver);
307 107
308 // 5. Let S be ? Get(C, @@species). 108 // 5. Let S be ? Get(C, @@species).
309 Node* const species_symbol = 109 Node* const species_symbol =
310 a->HeapConstant(isolate->factory()->species_symbol()); 110 HeapConstant(isolate->factory()->species_symbol());
311 Node* const species = 111 Node* const species =
312 a->CallStub(getproperty_callable, context, constructor, species_symbol); 112 CallStub(getproperty_callable, context, constructor, species_symbol);
313 113
314 // 6. If S is either undefined or null, return defaultConstructor. 114 // 6. If S is either undefined or null, return defaultConstructor.
315 a->GotoIf(a->IsUndefined(species), &out); 115 GotoIf(IsUndefined(species), &out);
316 a->GotoIf(a->WordEqual(species, a->NullConstant()), &out); 116 GotoIf(WordEqual(species, NullConstant()), &out);
317 117
318 // 7. If IsConstructor(S) is true, return S. 118 // 7. If IsConstructor(S) is true, return S.
319 Label throw_error(a); 119 Label throw_error(this);
320 Node* species_bitfield = a->LoadMapBitField(a->LoadMap(species)); 120 Node* species_bitfield = LoadMapBitField(LoadMap(species));
321 a->GotoUnless( 121 GotoUnless(Word32Equal(Word32And(species_bitfield,
322 a->Word32Equal(a->Word32And(species_bitfield, 122 Int32Constant((1 << Map::kIsConstructor))),
323 a->Int32Constant((1 << Map::kIsConstructor))), 123 Int32Constant(1 << Map::kIsConstructor)),
324 a->Int32Constant(1 << Map::kIsConstructor)), 124 &throw_error);
325 &throw_error);
326 var_result.Bind(species); 125 var_result.Bind(species);
327 a->Goto(&out); 126 Goto(&out);
328 127
329 // 8. Throw a TypeError exception. 128 // 8. Throw a TypeError exception.
330 a->Bind(&throw_error); 129 Bind(&throw_error);
331 { 130 {
332 Node* const message_id = 131 Node* const message_id =
333 a->SmiConstant(MessageTemplate::kSpeciesNotConstructor); 132 SmiConstant(MessageTemplate::kSpeciesNotConstructor);
334 a->CallRuntime(Runtime::kThrowTypeError, context, message_id); 133 CallRuntime(Runtime::kThrowTypeError, context, message_id);
335 a->Goto(&out); 134 Goto(&out);
336 } 135 }
337 136
338 a->Bind(&out); 137 Bind(&out);
339 return var_result.value(); 138 return var_result.value();
340 } 139 }
341 140
342 void AppendPromiseCallback(CodeStubAssembler* a, int offset, 141 void PromiseBuiltinsAssembler::AppendPromiseCallback(int offset, Node* promise,
343 compiler::Node* promise, compiler::Node* value) { 142 Node* value) {
344 typedef compiler::Node Node; 143 Node* elements = LoadObjectField(promise, offset);
144 Node* length = LoadFixedArrayBaseLength(elements);
145 CodeStubAssembler::ParameterMode mode = OptimalParameterMode();
146 length = TaggedToParameter(length, mode);
345 147
346 Node* elements = a->LoadObjectField(promise, offset); 148 Node* delta = IntPtrOrSmiConstant(1, mode);
347 Node* length = a->LoadFixedArrayBaseLength(elements); 149 Node* new_capacity = IntPtrOrSmiAdd(length, delta, mode);
348 CodeStubAssembler::ParameterMode mode = a->OptimalParameterMode();
349 length = a->TaggedToParameter(length, mode);
350
351 Node* delta = a->IntPtrOrSmiConstant(1, mode);
352 Node* new_capacity = a->IntPtrOrSmiAdd(length, delta, mode);
353 150
354 const ElementsKind kind = FAST_ELEMENTS; 151 const ElementsKind kind = FAST_ELEMENTS;
355 const WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER; 152 const WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER;
356 const CodeStubAssembler::AllocationFlags flags = 153 const CodeStubAssembler::AllocationFlags flags =
357 CodeStubAssembler::kAllowLargeObjectAllocation; 154 CodeStubAssembler::kAllowLargeObjectAllocation;
358 int additional_offset = 0; 155 int additional_offset = 0;
359 156
360 Node* new_elements = a->AllocateFixedArray(kind, new_capacity, mode, flags); 157 Node* new_elements = AllocateFixedArray(kind, new_capacity, mode, flags);
361 158
362 a->CopyFixedArrayElements(kind, elements, new_elements, length, barrier_mode, 159 CopyFixedArrayElements(kind, elements, new_elements, length, barrier_mode,
363 mode); 160 mode);
364 a->StoreFixedArrayElement(new_elements, length, value, barrier_mode, 161 StoreFixedArrayElement(new_elements, length, value, barrier_mode,
365 additional_offset, mode); 162 additional_offset, mode);
366 163
367 a->StoreObjectField(promise, offset, new_elements); 164 StoreObjectField(promise, offset, new_elements);
368 } 165 }
369 166
370 compiler::Node* InternalPerformPromiseThen(CodeStubAssembler* a, 167 Node* PromiseBuiltinsAssembler::InternalPerformPromiseThen(Node* context,
371 compiler::Node* context, 168 Node* promise,
372 compiler::Node* promise, 169 Node* on_resolve,
373 compiler::Node* on_resolve, 170 Node* on_reject,
374 compiler::Node* on_reject, 171 Node* deferred) {
375 compiler::Node* deferred) { 172 Node* const native_context = LoadNativeContext(context);
376 typedef CodeStubAssembler::Variable Variable; 173
377 typedef CodeStubAssembler::Label Label; 174 Variable var_on_resolve(this, MachineRepresentation::kTagged),
378 typedef compiler::Node Node; 175 var_on_reject(this, MachineRepresentation::kTagged);
379 Isolate* isolate = a->isolate();
380 Node* const native_context = a->LoadNativeContext(context);
381
382 Variable var_on_resolve(a, MachineRepresentation::kTagged),
383 var_on_reject(a, MachineRepresentation::kTagged);
384 176
385 var_on_resolve.Bind(on_resolve); 177 var_on_resolve.Bind(on_resolve);
386 var_on_reject.Bind(on_reject); 178 var_on_reject.Bind(on_reject);
387 179
388 Label out(a), if_onresolvenotcallable(a), onrejectcheck(a), 180 Label out(this), if_onresolvenotcallable(this), onrejectcheck(this),
389 append_callbacks(a); 181 append_callbacks(this);
390 a->GotoIf(a->TaggedIsSmi(on_resolve), &if_onresolvenotcallable); 182 GotoIf(TaggedIsSmi(on_resolve), &if_onresolvenotcallable);
391 183
392 Node* const on_resolve_map = a->LoadMap(on_resolve); 184 Node* const on_resolve_map = LoadMap(on_resolve);
393 a->Branch(a->IsCallableMap(on_resolve_map), &onrejectcheck, 185 Branch(IsCallableMap(on_resolve_map), &onrejectcheck,
394 &if_onresolvenotcallable); 186 &if_onresolvenotcallable);
395 187
396 a->Bind(&if_onresolvenotcallable); 188 Bind(&if_onresolvenotcallable);
397 { 189 {
398 var_on_resolve.Bind(a->LoadContextElement( 190 var_on_resolve.Bind(LoadContextElement(
399 native_context, Context::PROMISE_ID_RESOLVE_HANDLER_INDEX)); 191 native_context, Context::PROMISE_ID_RESOLVE_HANDLER_INDEX));
400 a->Goto(&onrejectcheck); 192 Goto(&onrejectcheck);
401 } 193 }
402 194
403 a->Bind(&onrejectcheck); 195 Bind(&onrejectcheck);
404 { 196 {
405 Label if_onrejectnotcallable(a); 197 Label if_onrejectnotcallable(this);
406 a->GotoIf(a->TaggedIsSmi(on_reject), &if_onrejectnotcallable); 198 GotoIf(TaggedIsSmi(on_reject), &if_onrejectnotcallable);
407 199
408 Node* const on_reject_map = a->LoadMap(on_reject); 200 Node* const on_reject_map = LoadMap(on_reject);
409 a->Branch(a->IsCallableMap(on_reject_map), &append_callbacks, 201 Branch(IsCallableMap(on_reject_map), &append_callbacks,
410 &if_onrejectnotcallable); 202 &if_onrejectnotcallable);
411 203
412 a->Bind(&if_onrejectnotcallable); 204 Bind(&if_onrejectnotcallable);
413 { 205 {
414 var_on_reject.Bind(a->LoadContextElement( 206 var_on_reject.Bind(LoadContextElement(
415 native_context, Context::PROMISE_ID_REJECT_HANDLER_INDEX)); 207 native_context, Context::PROMISE_ID_REJECT_HANDLER_INDEX));
416 a->Goto(&append_callbacks); 208 Goto(&append_callbacks);
417 } 209 }
418 } 210 }
419 211
420 a->Bind(&append_callbacks); 212 Bind(&append_callbacks);
421 { 213 {
422 Label fulfilled_check(a); 214 Label fulfilled_check(this);
423 Node* const status = a->LoadObjectField(promise, JSPromise::kStatusOffset); 215 Node* const status = LoadObjectField(promise, JSPromise::kStatusOffset);
424 a->GotoUnless(a->SmiEqual(status, a->SmiConstant(kPromisePending)), 216 GotoUnless(SmiEqual(status, SmiConstant(kPromisePending)),
425 &fulfilled_check); 217 &fulfilled_check);
426 218
427 Node* const existing_deferred = 219 Node* const existing_deferred =
428 a->LoadObjectField(promise, JSPromise::kDeferredOffset); 220 LoadObjectField(promise, JSPromise::kDeferredOffset);
429 221
430 Label if_noexistingcallbacks(a), if_existingcallbacks(a); 222 Label if_noexistingcallbacks(this), if_existingcallbacks(this);
431 a->Branch(a->IsUndefined(existing_deferred), &if_noexistingcallbacks, 223 Branch(IsUndefined(existing_deferred), &if_noexistingcallbacks,
432 &if_existingcallbacks); 224 &if_existingcallbacks);
433 225
434 a->Bind(&if_noexistingcallbacks); 226 Bind(&if_noexistingcallbacks);
435 { 227 {
436 // Store callbacks directly in the slots. 228 // Store callbacks directly in the slots.
437 a->StoreObjectField(promise, JSPromise::kDeferredOffset, deferred); 229 StoreObjectField(promise, JSPromise::kDeferredOffset, deferred);
438 a->StoreObjectField(promise, JSPromise::kFulfillReactionsOffset, 230 StoreObjectField(promise, JSPromise::kFulfillReactionsOffset,
439 var_on_resolve.value()); 231 var_on_resolve.value());
440 a->StoreObjectField(promise, JSPromise::kRejectReactionsOffset, 232 StoreObjectField(promise, JSPromise::kRejectReactionsOffset,
441 var_on_reject.value()); 233 var_on_reject.value());
442 a->Goto(&out); 234 Goto(&out);
443 } 235 }
444 236
445 a->Bind(&if_existingcallbacks); 237 Bind(&if_existingcallbacks);
446 { 238 {
447 Label if_singlecallback(a), if_multiplecallbacks(a); 239 Label if_singlecallback(this), if_multiplecallbacks(this);
448 a->BranchIfJSObject(existing_deferred, &if_singlecallback, 240 BranchIfJSObject(existing_deferred, &if_singlecallback,
449 &if_multiplecallbacks); 241 &if_multiplecallbacks);
450 242
451 a->Bind(&if_singlecallback); 243 Bind(&if_singlecallback);
452 { 244 {
453 // Create new FixedArrays to store callbacks, and migrate 245 // Create new FixedArrays to store callbacks, and migrate
454 // existing callbacks. 246 // existing callbacks.
455 Node* const deferreds = 247 Node* const deferreds =
456 a->AllocateFixedArray(FAST_ELEMENTS, a->IntPtrConstant(2)); 248 AllocateFixedArray(FAST_ELEMENTS, IntPtrConstant(2));
457 a->StoreFixedArrayElement(deferreds, 0, existing_deferred); 249 StoreFixedArrayElement(deferreds, 0, existing_deferred);
458 a->StoreFixedArrayElement(deferreds, 1, deferred); 250 StoreFixedArrayElement(deferreds, 1, deferred);
459 251
460 Node* const fulfill_reactions = 252 Node* const fulfill_reactions =
461 a->AllocateFixedArray(FAST_ELEMENTS, a->IntPtrConstant(2)); 253 AllocateFixedArray(FAST_ELEMENTS, IntPtrConstant(2));
462 a->StoreFixedArrayElement( 254 StoreFixedArrayElement(
463 fulfill_reactions, 0, 255 fulfill_reactions, 0,
464 a->LoadObjectField(promise, JSPromise::kFulfillReactionsOffset)); 256 LoadObjectField(promise, JSPromise::kFulfillReactionsOffset));
465 a->StoreFixedArrayElement(fulfill_reactions, 1, var_on_resolve.value()); 257 StoreFixedArrayElement(fulfill_reactions, 1, var_on_resolve.value());
466 258
467 Node* const reject_reactions = 259 Node* const reject_reactions =
468 a->AllocateFixedArray(FAST_ELEMENTS, a->IntPtrConstant(2)); 260 AllocateFixedArray(FAST_ELEMENTS, IntPtrConstant(2));
469 a->StoreFixedArrayElement( 261 StoreFixedArrayElement(
470 reject_reactions, 0, 262 reject_reactions, 0,
471 a->LoadObjectField(promise, JSPromise::kRejectReactionsOffset)); 263 LoadObjectField(promise, JSPromise::kRejectReactionsOffset));
472 a->StoreFixedArrayElement(reject_reactions, 1, var_on_reject.value()); 264 StoreFixedArrayElement(reject_reactions, 1, var_on_reject.value());
473 265
474 // Store new FixedArrays in promise. 266 // Store new FixedArrays in promise.
475 a->StoreObjectField(promise, JSPromise::kDeferredOffset, deferreds); 267 StoreObjectField(promise, JSPromise::kDeferredOffset, deferreds);
476 a->StoreObjectField(promise, JSPromise::kFulfillReactionsOffset, 268 StoreObjectField(promise, JSPromise::kFulfillReactionsOffset,
477 fulfill_reactions); 269 fulfill_reactions);
478 a->StoreObjectField(promise, JSPromise::kRejectReactionsOffset, 270 StoreObjectField(promise, JSPromise::kRejectReactionsOffset,
479 reject_reactions); 271 reject_reactions);
480 a->Goto(&out); 272 Goto(&out);
481 } 273 }
482 274
483 a->Bind(&if_multiplecallbacks); 275 Bind(&if_multiplecallbacks);
484 { 276 {
485 AppendPromiseCallback(a, JSPromise::kDeferredOffset, promise, deferred); 277 AppendPromiseCallback(JSPromise::kDeferredOffset, promise, deferred);
486 AppendPromiseCallback(a, JSPromise::kFulfillReactionsOffset, promise, 278 AppendPromiseCallback(JSPromise::kFulfillReactionsOffset, promise,
487 var_on_resolve.value()); 279 var_on_resolve.value());
488 AppendPromiseCallback(a, JSPromise::kRejectReactionsOffset, promise, 280 AppendPromiseCallback(JSPromise::kRejectReactionsOffset, promise,
489 var_on_reject.value()); 281 var_on_reject.value());
490 a->Goto(&out); 282 Goto(&out);
491 } 283 }
492 } 284 }
493 285
494 a->Bind(&fulfilled_check); 286 Bind(&fulfilled_check);
495 { 287 {
496 Label reject(a); 288 Label reject(this);
497 Node* const result = 289 Node* const result = LoadObjectField(promise, JSPromise::kResultOffset);
498 a->LoadObjectField(promise, JSPromise::kResultOffset); 290 GotoUnless(WordEqual(status, SmiConstant(kPromiseFulfilled)), &reject);
499 a->GotoUnless(a->WordEqual(status, a->SmiConstant(kPromiseFulfilled)),
500 &reject);
501 291
502 // TODO(gsathya): Move this to TF. 292 // TODO(gsathya): Move this to TF.
503 a->CallRuntime(Runtime::kEnqueuePromiseReactionJob, context, promise, 293 CallRuntime(Runtime::kEnqueuePromiseReactionJob, context, promise, result,
504 result, var_on_resolve.value(), deferred, 294 var_on_resolve.value(), deferred,
505 a->SmiConstant(kPromiseFulfilled)); 295 SmiConstant(kPromiseFulfilled));
506 a->Goto(&out); 296 Goto(&out);
507 297
508 a->Bind(&reject); 298 Bind(&reject);
509 { 299 {
510 Node* const has_handler = PromiseHasHandler(a, promise); 300 Node* const has_handler = PromiseHasHandler(promise);
511 Label enqueue(a); 301 Label enqueue(this);
512 302
513 // TODO(gsathya): Fold these runtime calls and move to TF. 303 // TODO(gsathya): Fold these runtime calls and move to TF.
514 a->GotoIf(has_handler, &enqueue); 304 GotoIf(has_handler, &enqueue);
515 a->CallRuntime(Runtime::kPromiseRevokeReject, context, promise); 305 CallRuntime(Runtime::kPromiseRevokeReject, context, promise);
516 a->Goto(&enqueue); 306 Goto(&enqueue);
517 307
518 a->Bind(&enqueue); 308 Bind(&enqueue);
519 { 309 {
520 a->CallRuntime(Runtime::kEnqueuePromiseReactionJob, context, promise, 310 CallRuntime(Runtime::kEnqueuePromiseReactionJob, context, promise,
521 result, var_on_reject.value(), deferred, 311 result, var_on_reject.value(), deferred,
522 a->SmiConstant(kPromiseRejected)); 312 SmiConstant(kPromiseRejected));
523 313
524 a->Goto(&out); 314 Goto(&out);
525 } 315 }
526 } 316 }
527 } 317 }
528 } 318 }
529 319
530 a->Bind(&out); 320 Bind(&out);
531 PromiseSetHasHandler(a, promise); 321 PromiseSetHasHandler(promise);
532 322
533 // TODO(gsathya): This call will be removed once we don't have to 323 // TODO(gsathya): This call will be removed once we don't have to
534 // deal with deferred objects. 324 // deal with deferred objects.
325 Isolate* isolate = this->isolate();
535 Callable getproperty_callable = CodeFactory::GetProperty(isolate); 326 Callable getproperty_callable = CodeFactory::GetProperty(isolate);
536 Node* const key = 327 Node* const key =
537 a->HeapConstant(isolate->factory()->NewStringFromAsciiChecked("promise")); 328 HeapConstant(isolate->factory()->NewStringFromAsciiChecked("promise"));
538 Node* const result = 329 Node* const result = CallStub(getproperty_callable, context, deferred, key);
539 a->CallStub(getproperty_callable, context, deferred, key);
540 330
541 return result; 331 return result;
542 } 332 }
543 333
544 } // namespace
545
546 void Builtins::Generate_PerformPromiseThen(
547 compiler::CodeAssemblerState* state) {
548 CodeStubAssembler a(state);
549 typedef compiler::Node Node;
550
551 Node* const promise = a.Parameter(1);
552 Node* const on_resolve = a.Parameter(2);
553 Node* const on_reject = a.Parameter(3);
554 Node* const deferred = a.Parameter(4);
555 Node* const context = a.Parameter(7);
556
557 Node* const result = InternalPerformPromiseThen(
558 &a, context, promise, on_resolve, on_reject, deferred);
559
560 // TODO(gsathya): This is unused, but value is returned according to spec.
561 a.Return(result);
562 }
563
564 void Builtins::Generate_PromiseThen(compiler::CodeAssemblerState* state) {
565 CodeStubAssembler a(state);
566 typedef compiler::Node Node;
567 typedef CodeStubAssembler::Label Label;
568 typedef CodeStubAssembler::Variable Variable;
569
570 // 1. Let promise be the this value.
571 Node* const promise = a.Parameter(0);
572 Node* const on_resolve = a.Parameter(1);
573 Node* const on_reject = a.Parameter(2);
574 Node* const context = a.Parameter(5);
575 Isolate* isolate = a.isolate();
576
577 // 2. If IsPromise(promise) is false, throw a TypeError exception.
578 a.ThrowIfNotInstanceType(context, promise, JS_PROMISE_TYPE,
579 "Promise.prototype.then");
580
581 Node* const native_context = a.LoadNativeContext(context);
582 Node* const promise_fun =
583 a.LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
584
585 // 3. Let C be ? SpeciesConstructor(promise, %Promise%).
586 Node* constructor =
587 SpeciesConstructor(&a, isolate, context, promise, promise_fun);
588
589 // 4. Let resultCapability be ? NewPromiseCapability(C).
590 Callable call_callable = CodeFactory::Call(isolate);
591 Label fast_promise_capability(&a), promise_capability(&a),
592 perform_promise_then(&a);
593 Variable var_deferred(&a, MachineRepresentation::kTagged);
594
595 a.Branch(a.WordEqual(promise_fun, constructor), &fast_promise_capability,
596 &promise_capability);
597
598 // TODO(gsathya): Remove deferred object and move
599 // NewPromiseCapbability functions to TF.
600 a.Bind(&fast_promise_capability);
601 {
602 // TODO(gsathya): Move this to TF.
603 Node* const promise_internal_capability = a.LoadContextElement(
604 native_context, Context::INTERNAL_PROMISE_CAPABILITY_INDEX);
605 Node* const capability =
606 a.CallJS(call_callable, context, promise_internal_capability,
607 a.UndefinedConstant());
608 var_deferred.Bind(capability);
609 a.Goto(&perform_promise_then);
610 }
611
612 a.Bind(&promise_capability);
613 {
614 // TODO(gsathya): Move this to TF.
615 Node* const new_promise_capability = a.LoadContextElement(
616 native_context, Context::NEW_PROMISE_CAPABILITY_INDEX);
617 Node* const capability =
618 a.CallJS(call_callable, context, new_promise_capability,
619 a.UndefinedConstant(), constructor);
620 var_deferred.Bind(capability);
621 a.Goto(&perform_promise_then);
622 }
623
624 // 5. Return PerformPromiseThen(promise, onFulfilled, onRejected,
625 // resultCapability).
626 a.Bind(&perform_promise_then);
627 Node* const result = InternalPerformPromiseThen(
628 &a, context, promise, on_resolve, on_reject, var_deferred.value());
629 a.Return(result);
630 }
631
632 namespace {
633
634 // Promise fast path implementations rely on unmodified JSPromise instances. 334 // Promise fast path implementations rely on unmodified JSPromise instances.
635 // We use a fairly coarse granularity for this and simply check whether both 335 // We use a fairly coarse granularity for this and simply check whether both
636 // the promise itself is unmodified (i.e. its map has not changed) and its 336 // the promise itself is unmodified (i.e. its map has not changed) and its
637 // prototype is unmodified. 337 // prototype is unmodified.
638 // TODO(gsathya): Refactor this out to prevent code dupe with builtins-regexp 338 // TODO(gsathya): Refactor this out to prevent code dupe with builtins-regexp
639 void BranchIfFastPath(CodeStubAssembler* a, compiler::Node* context, 339 void PromiseBuiltinsAssembler::BranchIfFastPath(Node* context, Node* promise,
640 compiler::Node* promise, 340 Label* if_isunmodified,
641 CodeStubAssembler::Label* if_isunmodified, 341 Label* if_ismodified) {
642 CodeStubAssembler::Label* if_ismodified) {
643 typedef compiler::Node Node;
644
645 // TODO(gsathya): Assert if promise is receiver 342 // TODO(gsathya): Assert if promise is receiver
646 Node* const map = a->LoadMap(promise); 343 Node* const map = LoadMap(promise);
647 Node* const native_context = a->LoadNativeContext(context); 344 Node* const native_context = LoadNativeContext(context);
648 Node* const promise_fun = 345 Node* const promise_fun =
649 a->LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX); 346 LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
650 Node* const initial_map = 347 Node* const initial_map =
651 a->LoadObjectField(promise_fun, JSFunction::kPrototypeOrInitialMapOffset); 348 LoadObjectField(promise_fun, JSFunction::kPrototypeOrInitialMapOffset);
652 Node* const has_initialmap = a->WordEqual(map, initial_map); 349 Node* const has_initialmap = WordEqual(map, initial_map);
653 350
654 a->GotoUnless(has_initialmap, if_ismodified); 351 GotoUnless(has_initialmap, if_ismodified);
655 352
656 Node* const initial_proto_initial_map = a->LoadContextElement( 353 Node* const initial_proto_initial_map =
657 native_context, Context::PROMISE_PROTOTYPE_MAP_INDEX); 354 LoadContextElement(native_context, Context::PROMISE_PROTOTYPE_MAP_INDEX);
658 Node* const proto_map = a->LoadMap(a->LoadMapPrototype(map)); 355 Node* const proto_map = LoadMap(LoadMapPrototype(map));
659 Node* const proto_has_initialmap = 356 Node* const proto_has_initialmap =
660 a->WordEqual(proto_map, initial_proto_initial_map); 357 WordEqual(proto_map, initial_proto_initial_map);
661 358
662 a->Branch(proto_has_initialmap, if_isunmodified, if_ismodified); 359 Branch(proto_has_initialmap, if_isunmodified, if_ismodified);
663 } 360 }
664 361
665 void InternalResolvePromise(CodeStubAssembler* a, compiler::Node* context, 362 void PromiseBuiltinsAssembler::InternalResolvePromise(Node* context,
666 compiler::Node* promise, compiler::Node* result, 363 Node* promise,
667 CodeStubAssembler::Label* out) { 364 Node* result,
668 typedef CodeStubAssembler::Variable Variable; 365 Label* out) {
669 typedef CodeStubAssembler::Label Label; 366 Isolate* isolate = this->isolate();
670 typedef compiler::Node Node; 367
671 368 Variable var_reason(this, MachineRepresentation::kTagged),
672 Isolate* isolate = a->isolate(); 369 var_then(this, MachineRepresentation::kTagged);
673 370
674 Variable var_reason(a, MachineRepresentation::kTagged), 371 Label do_enqueue(this), fulfill(this), if_cycle(this, Label::kDeferred),
675 var_then(a, MachineRepresentation::kTagged); 372 if_rejectpromise(this, Label::kDeferred);
676
677 Label do_enqueue(a), fulfill(a), if_cycle(a, Label::kDeferred),
678 if_rejectpromise(a, Label::kDeferred);
679 373
680 // 6. If SameValue(resolution, promise) is true, then 374 // 6. If SameValue(resolution, promise) is true, then
681 a->GotoIf(a->SameValue(promise, result, context), &if_cycle); 375 GotoIf(SameValue(promise, result, context), &if_cycle);
682 376
683 // 7. If Type(resolution) is not Object, then 377 // 7. If Type(resolution) is not Object, then
684 a->GotoIf(a->TaggedIsSmi(result), &fulfill); 378 GotoIf(TaggedIsSmi(result), &fulfill);
685 a->GotoUnless(a->IsJSReceiver(result), &fulfill); 379 GotoUnless(IsJSReceiver(result), &fulfill);
686 380
687 Label if_nativepromise(a), if_notnativepromise(a, Label::kDeferred); 381 Label if_nativepromise(this), if_notnativepromise(this, Label::kDeferred);
688 BranchIfFastPath(a, context, result, &if_nativepromise, &if_notnativepromise); 382 BranchIfFastPath(context, result, &if_nativepromise, &if_notnativepromise);
689 383
690 // Resolution is a native promise and if it's already resolved or 384 // Resolution is a native promise and if it's already resolved or
691 // rejected, shortcircuit the resolution procedure by directly 385 // rejected, shortcircuit the resolution procedure by directly
692 // reusing the value from the promise. 386 // reusing the value from the promise.
693 a->Bind(&if_nativepromise); 387 Bind(&if_nativepromise);
694 { 388 {
695 Node* const thenable_status = 389 Node* const thenable_status =
696 a->LoadObjectField(result, JSPromise::kStatusOffset); 390 LoadObjectField(result, JSPromise::kStatusOffset);
697 Node* const thenable_value = 391 Node* const thenable_value =
698 a->LoadObjectField(result, JSPromise::kResultOffset); 392 LoadObjectField(result, JSPromise::kResultOffset);
699 393
700 Label if_isnotpending(a); 394 Label if_isnotpending(this);
701 a->GotoUnless(a->SmiEqual(a->SmiConstant(kPromisePending), thenable_status), 395 GotoUnless(SmiEqual(SmiConstant(kPromisePending), thenable_status),
702 &if_isnotpending); 396 &if_isnotpending);
703 397
704 // TODO(gsathya): Use a marker here instead of the actual then 398 // TODO(gsathya): Use a marker here instead of the actual then
705 // callback, and check for the marker in PromiseResolveThenableJob 399 // callback, and check for the marker in PromiseResolveThenableJob
706 // and perform PromiseThen. 400 // and perform PromiseThen.
707 Node* const native_context = a->LoadNativeContext(context); 401 Node* const native_context = LoadNativeContext(context);
708 Node* const then = 402 Node* const then =
709 a->LoadContextElement(native_context, Context::PROMISE_THEN_INDEX); 403 LoadContextElement(native_context, Context::PROMISE_THEN_INDEX);
710 var_then.Bind(then); 404 var_then.Bind(then);
711 a->Goto(&do_enqueue); 405 Goto(&do_enqueue);
712 406
713 a->Bind(&if_isnotpending); 407 Bind(&if_isnotpending);
714 { 408 {
715 Label if_fulfilled(a), if_rejected(a); 409 Label if_fulfilled(this), if_rejected(this);
716 a->Branch(a->SmiEqual(a->SmiConstant(kPromiseFulfilled), thenable_status), 410 Branch(SmiEqual(SmiConstant(kPromiseFulfilled), thenable_status),
717 &if_fulfilled, &if_rejected); 411 &if_fulfilled, &if_rejected);
718 412
719 a->Bind(&if_fulfilled); 413 Bind(&if_fulfilled);
720 { 414 {
721 a->CallRuntime(Runtime::kPromiseFulfill, context, promise, 415 CallRuntime(Runtime::kPromiseFulfill, context, promise,
722 a->SmiConstant(kPromiseFulfilled), thenable_value); 416 SmiConstant(kPromiseFulfilled), thenable_value);
723 PromiseSetHasHandler(a, promise); 417 PromiseSetHasHandler(promise);
724 a->Goto(out); 418 Goto(out);
725 } 419 }
726 420
727 a->Bind(&if_rejected); 421 Bind(&if_rejected);
728 { 422 {
729 Label reject(a); 423 Label reject(this);
730 Node* const has_handler = PromiseHasHandler(a, result); 424 Node* const has_handler = PromiseHasHandler(result);
731 425
732 // Promise has already been rejected, but had no handler. 426 // Promise has already been rejected, but had no handler.
733 // Revoke previously triggered reject event. 427 // Revoke previously triggered reject event.
734 a->GotoIf(has_handler, &reject); 428 GotoIf(has_handler, &reject);
735 a->CallRuntime(Runtime::kPromiseRevokeReject, context, result); 429 CallRuntime(Runtime::kPromiseRevokeReject, context, result);
736 a->Goto(&reject); 430 Goto(&reject);
737 431
738 a->Bind(&reject); 432 Bind(&reject);
739 // Don't cause a debug event as this case is forwarding a rejection 433 // Don't cause a debug event as this case is forwarding a rejection
740 a->CallRuntime(Runtime::kPromiseReject, context, promise, 434 CallRuntime(Runtime::kPromiseReject, context, promise, thenable_value,
741 thenable_value, a->FalseConstant()); 435 FalseConstant());
742 PromiseSetHasHandler(a, result); 436 PromiseSetHasHandler(result);
743 a->Goto(out); 437 Goto(out);
744 } 438 }
745 } 439 }
746 } 440 }
747 441
748 a->Bind(&if_notnativepromise); 442 Bind(&if_notnativepromise);
749 { 443 {
750 // 8. Let then be Get(resolution, "then"). 444 // 8. Let then be Get(resolution, "then").
751 Node* const then_str = a->HeapConstant(isolate->factory()->then_string()); 445 Node* const then_str = HeapConstant(isolate->factory()->then_string());
752 Callable getproperty_callable = CodeFactory::GetProperty(a->isolate()); 446 Callable getproperty_callable = CodeFactory::GetProperty(isolate);
753 Node* const then = 447 Node* const then =
754 a->CallStub(getproperty_callable, context, result, then_str); 448 CallStub(getproperty_callable, context, result, then_str);
755 449
756 // 9. If then is an abrupt completion, then 450 // 9. If then is an abrupt completion, then
757 a->GotoIfException(then, &if_rejectpromise, &var_reason); 451 GotoIfException(then, &if_rejectpromise, &var_reason);
758 452
759 // 11. If IsCallable(thenAction) is false, then 453 // 11. If IsCallable(thenAction) is false, then
760 a->GotoIf(a->TaggedIsSmi(then), &fulfill); 454 GotoIf(TaggedIsSmi(then), &fulfill);
761 Node* const then_map = a->LoadMap(then); 455 Node* const then_map = LoadMap(then);
762 a->GotoUnless(a->IsCallableMap(then_map), &fulfill); 456 GotoUnless(IsCallableMap(then_map), &fulfill);
763 var_then.Bind(then); 457 var_then.Bind(then);
764 a->Goto(&do_enqueue); 458 Goto(&do_enqueue);
765 } 459 }
766 460
767 a->Bind(&do_enqueue); 461 Bind(&do_enqueue);
768 { 462 {
769 Label enqueue(a); 463 Label enqueue(this);
770 a->GotoUnless(a->IsDebugActive(), &enqueue); 464 GotoUnless(IsDebugActive(), &enqueue);
771 a->GotoIf(a->TaggedIsSmi(result), &enqueue); 465 GotoIf(TaggedIsSmi(result), &enqueue);
772 a->GotoUnless(a->HasInstanceType(result, JS_PROMISE_TYPE), &enqueue); 466 GotoUnless(HasInstanceType(result, JS_PROMISE_TYPE), &enqueue);
773 // Mark the dependency of the new promise on the resolution 467 // Mark the dependency of the new promise on the resolution
774 Node* const key = 468 Node* const key =
775 a->HeapConstant(isolate->factory()->promise_handled_by_symbol()); 469 HeapConstant(isolate->factory()->promise_handled_by_symbol());
776 a->CallRuntime(Runtime::kSetProperty, context, result, key, promise, 470 CallRuntime(Runtime::kSetProperty, context, result, key, promise,
777 a->SmiConstant(STRICT)); 471 SmiConstant(STRICT));
778 a->Goto(&enqueue); 472 Goto(&enqueue);
779 473
780 // 12. Perform EnqueueJob("PromiseJobs", 474 // 12. Perform EnqueueJob("PromiseJobs",
781 // PromiseResolveThenableJob, « promise, resolution, thenAction 475 // PromiseResolveThenableJob, « promise, resolution, thenAction
782 // »). 476 // »).
783 a->Bind(&enqueue); 477 Bind(&enqueue);
784 a->CallRuntime(Runtime::kEnqueuePromiseResolveThenableJob, context, promise, 478 CallRuntime(Runtime::kEnqueuePromiseResolveThenableJob, context, promise,
785 result, var_then.value()); 479 result, var_then.value());
786 a->Goto(out); 480 Goto(out);
787 } 481 }
482
788 // 7.b Return FulfillPromise(promise, resolution). 483 // 7.b Return FulfillPromise(promise, resolution).
789 a->Bind(&fulfill); 484 Bind(&fulfill);
790 { 485 {
791 a->CallRuntime(Runtime::kPromiseFulfill, context, promise, 486 CallRuntime(Runtime::kPromiseFulfill, context, promise,
792 a->SmiConstant(kPromiseFulfilled), result); 487 SmiConstant(kPromiseFulfilled), result);
793 a->Goto(out); 488 Goto(out);
794 } 489 }
795 490
796 a->Bind(&if_cycle); 491 Bind(&if_cycle);
797 { 492 {
798 // 6.a Let selfResolutionError be a newly created TypeError object. 493 // 6.a Let selfResolutionError be a newly created TypeError object.
799 Node* const message_id = a->SmiConstant(MessageTemplate::kPromiseCyclic); 494 Node* const message_id = SmiConstant(MessageTemplate::kPromiseCyclic);
800 Node* const error = 495 Node* const error =
801 a->CallRuntime(Runtime::kNewTypeError, context, message_id, result); 496 CallRuntime(Runtime::kNewTypeError, context, message_id, result);
802 var_reason.Bind(error); 497 var_reason.Bind(error);
803 498
804 // 6.b Return RejectPromise(promise, selfResolutionError). 499 // 6.b Return RejectPromise(promise, selfResolutionError).
805 a->Goto(&if_rejectpromise); 500 Goto(&if_rejectpromise);
806 } 501 }
807 502
808 // 9.a Return RejectPromise(promise, then.[[Value]]). 503 // 9.a Return RejectPromise(promise, then.[[Value]]).
809 a->Bind(&if_rejectpromise); 504 Bind(&if_rejectpromise);
810 { 505 {
811 a->CallRuntime(Runtime::kPromiseReject, context, promise, 506 CallRuntime(Runtime::kPromiseReject, context, promise, var_reason.value(),
812 var_reason.value(), a->TrueConstant()); 507 TrueConstant());
813 a->Goto(out); 508 Goto(out);
814 } 509 }
815 } 510 }
816 511
817 } // namespace 512 // ES#sec-promise-reject-functions
513 // Promise Reject Functions
514 BUILTIN(PromiseRejectClosure) {
515 HandleScope scope(isolate);
516
517 Handle<Context> context(isolate->context(), isolate);
518
519 if (PromiseUtils::HasAlreadyVisited(context)) {
520 return isolate->heap()->undefined_value();
521 }
522
523 PromiseUtils::SetAlreadyVisited(context);
524 Handle<Object> value = args.atOrUndefined(isolate, 1);
525 Handle<JSObject> promise = handle(PromiseUtils::GetPromise(context), isolate);
526 Handle<Object> debug_event =
527 handle(PromiseUtils::GetDebugEvent(context), isolate);
528 MaybeHandle<Object> maybe_result;
529 Handle<Object> argv[] = {promise, value, debug_event};
530 RETURN_FAILURE_ON_EXCEPTION(
531 isolate, Execution::Call(isolate, isolate->promise_internal_reject(),
532 isolate->factory()->undefined_value(),
533 arraysize(argv), argv));
534 return isolate->heap()->undefined_value();
535 }
536
537 // ES#sec-createresolvingfunctions
538 // CreateResolvingFunctions ( promise )
539 BUILTIN(CreateResolvingFunctions) {
540 HandleScope scope(isolate);
541 DCHECK_EQ(3, args.length());
542
543 Handle<JSObject> promise = args.at<JSObject>(1);
544 Handle<Object> debug_event = args.at<Object>(2);
545 Handle<JSFunction> resolve, reject;
546
547 PromiseUtils::CreateResolvingFunctions(isolate, promise, debug_event,
548 &resolve, &reject);
549
550 Handle<FixedArray> result = isolate->factory()->NewFixedArray(2);
551 result->set(0, *resolve);
552 result->set(1, *reject);
553
554 return *isolate->factory()->NewJSArrayWithElements(result, FAST_ELEMENTS, 2,
555 NOT_TENURED);
556 }
557
558 TF_BUILTIN(PromiseConstructor, PromiseBuiltinsAssembler) {
559 Node* const executor = Parameter(1);
560 Node* const new_target = Parameter(2);
561 Node* const context = Parameter(4);
562 Isolate* isolate = this->isolate();
563
564 Label if_targetisundefined(this, Label::kDeferred);
565
566 GotoIf(IsUndefined(new_target), &if_targetisundefined);
567
568 Label if_notcallable(this, Label::kDeferred);
569
570 GotoIf(TaggedIsSmi(executor), &if_notcallable);
571
572 Node* const executor_map = LoadMap(executor);
573 GotoUnless(IsCallableMap(executor_map), &if_notcallable);
574
575 Node* const native_context = LoadNativeContext(context);
576 Node* const promise_fun =
577 LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
578 Node* const is_debug_active = IsDebugActive();
579 Label if_targetisnotmodified(this),
580 if_targetismodified(this, Label::kDeferred), run_executor(this),
581 debug_push(this, Label::kDeferred), init(this);
582
583 Branch(WordEqual(promise_fun, new_target), &if_targetisnotmodified,
584 &if_targetismodified);
585
586 Variable var_result(this, MachineRepresentation::kTagged),
587 var_reject_call(this, MachineRepresentation::kTagged),
588 var_reason(this, MachineRepresentation::kTagged);
589
590 Bind(&if_targetisnotmodified);
591 {
592 Node* const instance = AllocateJSPromise(context);
593 var_result.Bind(instance);
594 Goto(&init);
595 }
596
597 Bind(&if_targetismodified);
598 {
599 Callable fast_new_object_stub = CodeFactory::FastNewObject(isolate);
600 Node* const instance =
601 CallStub(fast_new_object_stub, context, promise_fun, new_target);
602
603 var_result.Bind(instance);
604 Goto(&init);
605 }
606
607 Bind(&init);
608 {
609 PromiseInit(var_result.value());
610 Branch(is_debug_active, &debug_push, &run_executor);
611 }
612
613 Bind(&debug_push);
614 {
615 CallRuntime(Runtime::kDebugPushPromise, context, var_result.value());
616 Goto(&run_executor);
617 }
618
619 Bind(&run_executor);
620 {
621 Label out(this), if_rejectpromise(this), debug_pop(this, Label::kDeferred);
622
623 // TODO(gsathya): Move this to TF.
624 Node* const resolving_functions = CallRuntime(
625 Runtime::kCreateResolvingFunctions, context, var_result.value());
626 Node* const resolve =
627 LoadFixedArrayElement(resolving_functions, IntPtrConstant(0));
628 Node* const reject =
629 LoadFixedArrayElement(resolving_functions, IntPtrConstant(1));
630 Callable call_callable = CodeFactory::Call(isolate);
631
632 Node* const maybe_exception = CallJS(call_callable, context, executor,
633 UndefinedConstant(), resolve, reject);
634
635 GotoIfException(maybe_exception, &if_rejectpromise, &var_reason);
636 Branch(is_debug_active, &debug_pop, &out);
637
638 Bind(&if_rejectpromise);
639 {
640 Callable call_callable = CodeFactory::Call(isolate);
641 CallJS(call_callable, context, reject, UndefinedConstant(),
642 var_reason.value());
643 Branch(is_debug_active, &debug_pop, &out);
644 }
645
646 Bind(&debug_pop);
647 {
648 CallRuntime(Runtime::kDebugPopPromise, context);
649 Goto(&out);
650 }
651 Bind(&out);
652 Return(var_result.value());
653 }
654
655 // 1. If NewTarget is undefined, throw a TypeError exception.
656 Bind(&if_targetisundefined);
657 {
658 Node* const message_id = SmiConstant(MessageTemplate::kNotAPromise);
659 CallRuntime(Runtime::kThrowTypeError, context, message_id, new_target);
660 Return(UndefinedConstant()); // Never reached.
661 }
662
663 // 2. If IsCallable(executor) is false, throw a TypeError exception.
664 Bind(&if_notcallable);
665 {
666 Node* const message_id =
667 SmiConstant(MessageTemplate::kResolverNotAFunction);
668 CallRuntime(Runtime::kThrowTypeError, context, message_id, executor);
669 Return(UndefinedConstant()); // Never reached.
670 }
671 }
672
673 TF_BUILTIN(PromiseInternalConstructor, PromiseBuiltinsAssembler) {
674 Node* const context = Parameter(3);
675 Node* const instance = AllocateJSPromise(context);
676 PromiseInit(instance);
677 Return(instance);
678 }
679
680 TF_BUILTIN(PromiseCreateAndSet, PromiseBuiltinsAssembler) {
681 Node* const status = Parameter(1);
682 Node* const result = Parameter(2);
683 Node* const context = Parameter(5);
684
685 Node* const instance = AllocateJSPromise(context);
686 PromiseSet(instance, status, result);
687 Return(instance);
688 }
689
690 TF_BUILTIN(IsPromise, PromiseBuiltinsAssembler) {
691 Node* const maybe_promise = Parameter(1);
692 Label if_notpromise(this, Label::kDeferred);
693
694 GotoIf(TaggedIsSmi(maybe_promise), &if_notpromise);
695
696 Node* const result =
697 SelectBooleanConstant(HasInstanceType(maybe_promise, JS_PROMISE_TYPE));
698 Return(result);
699
700 Bind(&if_notpromise);
701 Return(FalseConstant());
702 }
703
704 TF_BUILTIN(PerformPromiseThen, PromiseBuiltinsAssembler) {
705 Node* const promise = Parameter(1);
706 Node* const on_resolve = Parameter(2);
707 Node* const on_reject = Parameter(3);
708 Node* const deferred = Parameter(4);
709 Node* const context = Parameter(7);
710
711 Node* const result = InternalPerformPromiseThen(context, promise, on_resolve,
712 on_reject, deferred);
713
714 // TODO(gsathya): This is unused, but value is returned according to spec.
715 Return(result);
716 }
717
718 TF_BUILTIN(PromiseThen, PromiseBuiltinsAssembler) {
719 // 1. Let promise be the this value.
720 Node* const promise = Parameter(0);
721 Node* const on_resolve = Parameter(1);
722 Node* const on_reject = Parameter(2);
723 Node* const context = Parameter(5);
724 Isolate* isolate = this->isolate();
725
726 // 2. If IsPromise(promise) is false, throw a TypeError exception.
727 ThrowIfNotInstanceType(context, promise, JS_PROMISE_TYPE,
728 "Promise.prototype.then");
729
730 Node* const native_context = LoadNativeContext(context);
731 Node* const promise_fun =
732 LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
733
734 // 3. Let C be ? SpeciesConstructor(promise, %Promise%).
735 Node* constructor = SpeciesConstructor(context, promise, promise_fun);
736
737 // 4. Let resultCapability be ? NewPromiseCapability(C).
738 Callable call_callable = CodeFactory::Call(isolate);
739 Label fast_promise_capability(this), promise_capability(this),
740 perform_promise_then(this);
741 Variable var_deferred(this, MachineRepresentation::kTagged);
742
743 Branch(WordEqual(promise_fun, constructor), &fast_promise_capability,
744 &promise_capability);
745
746 // TODO(gsathya): Remove deferred object and move
747 // NewPromiseCapabability functions to TF.
748 Bind(&fast_promise_capability);
749 {
750 // TODO(gsathya): Move this to TF.
751 Node* const promise_internal_capability = LoadContextElement(
752 native_context, Context::INTERNAL_PROMISE_CAPABILITY_INDEX);
753 Node* const capability =
754 CallJS(call_callable, context, promise_internal_capability,
755 UndefinedConstant());
756 var_deferred.Bind(capability);
757 Goto(&perform_promise_then);
758 }
759
760 Bind(&promise_capability);
761 {
762 // TODO(gsathya): Move this to TF.
763 Node* const new_promise_capability = LoadContextElement(
764 native_context, Context::NEW_PROMISE_CAPABILITY_INDEX);
765 Node* const capability =
766 CallJS(call_callable, context, new_promise_capability,
767 UndefinedConstant(), constructor);
768 var_deferred.Bind(capability);
769 Goto(&perform_promise_then);
770 }
771
772 // 5. Return PerformPromiseThen(promise, onFulfilled, onRejected,
773 // resultCapability).
774 Bind(&perform_promise_then);
775 Node* const result = InternalPerformPromiseThen(
776 context, promise, on_resolve, on_reject, var_deferred.value());
777 Return(result);
778 }
818 779
819 // ES#sec-promise-resolve-functions 780 // ES#sec-promise-resolve-functions
820 // Promise Resolve Functions 781 // Promise Resolve Functions
821 void Builtins::Generate_PromiseResolveClosure( 782 TF_BUILTIN(PromiseResolveClosure, PromiseBuiltinsAssembler) {
822 compiler::CodeAssemblerState* state) { 783 Node* const value = Parameter(1);
823 CodeStubAssembler a(state); 784 Node* const context = Parameter(4);
824 typedef compiler::Node Node; 785
825 typedef CodeStubAssembler::Label Label; 786 Label out(this);
826
827 Node* const value = a.Parameter(1);
828 Node* const context = a.Parameter(4);
829
830 Label out(&a);
831 787
832 // 3. Let alreadyResolved be F.[[AlreadyResolved]]. 788 // 3. Let alreadyResolved be F.[[AlreadyResolved]].
833 Node* const has_already_visited_slot = 789 Node* const has_already_visited_slot =
834 a.IntPtrConstant(PromiseUtils::kAlreadyVisitedSlot); 790 IntPtrConstant(PromiseUtils::kAlreadyVisitedSlot);
835 791
836 Node* const has_already_visited = 792 Node* const has_already_visited =
837 a.LoadFixedArrayElement(context, has_already_visited_slot); 793 LoadFixedArrayElement(context, has_already_visited_slot);
838 794
839 // 4. If alreadyResolved.[[Value]] is true, return undefined. 795 // 4. If alreadyResolved.[[Value]] is true, return undefined.
840 a.GotoIf(a.SmiEqual(has_already_visited, a.SmiConstant(1)), &out); 796 GotoIf(SmiEqual(has_already_visited, SmiConstant(1)), &out);
841 797
842 // 5.Set alreadyResolved.[[Value]] to true. 798 // 5.Set alreadyResolved.[[Value]] to true.
843 a.StoreFixedArrayElement(context, has_already_visited_slot, a.SmiConstant(1)); 799 StoreFixedArrayElement(context, has_already_visited_slot, SmiConstant(1));
844 800
845 // 2. Let promise be F.[[Promise]]. 801 // 2. Let promise be F.[[Promise]].
846 Node* const promise = a.LoadFixedArrayElement( 802 Node* const promise = LoadFixedArrayElement(
847 context, a.IntPtrConstant(PromiseUtils::kPromiseSlot)); 803 context, IntPtrConstant(PromiseUtils::kPromiseSlot));
848 804
849 InternalResolvePromise(&a, context, promise, value, &out); 805 InternalResolvePromise(context, promise, value, &out);
850 806
851 a.Bind(&out); 807 Bind(&out);
852 a.Return(a.UndefinedConstant()); 808 Return(UndefinedConstant());
853 } 809 }
854 810
855 void Builtins::Generate_ResolvePromise(compiler::CodeAssemblerState* state) { 811 TF_BUILTIN(ResolvePromise, PromiseBuiltinsAssembler) {
856 CodeStubAssembler a(state); 812 Node* const promise = Parameter(1);
857 typedef compiler::Node Node; 813 Node* const result = Parameter(2);
858 typedef CodeStubAssembler::Label Label; 814 Node* const context = Parameter(5);
859 815
860 Node* const promise = a.Parameter(1); 816 Label out(this);
861 Node* const result = a.Parameter(2); 817 InternalResolvePromise(context, promise, result, &out);
862 Node* const context = a.Parameter(5); 818
863 819 Bind(&out);
864 Label out(&a); 820 Return(UndefinedConstant());
865 InternalResolvePromise(&a, context, promise, result, &out); 821 }
866 822
867 a.Bind(&out); 823 TF_BUILTIN(PromiseHandleReject, PromiseBuiltinsAssembler) {
868 a.Return(a.UndefinedConstant());
869 }
870
871 void Builtins::Generate_PromiseHandleReject(
872 compiler::CodeAssemblerState* state) {
873 CodeStubAssembler a(state);
874 typedef compiler::Node Node;
875 typedef CodeStubAssembler::Label Label;
876 typedef CodeStubAssembler::Variable Variable;
877 typedef PromiseHandleRejectDescriptor Descriptor; 824 typedef PromiseHandleRejectDescriptor Descriptor;
878 825
879 Node* const promise = a.Parameter(Descriptor::kPromise); 826 Node* const promise = Parameter(Descriptor::kPromise);
880 Node* const on_reject = a.Parameter(Descriptor::kOnReject); 827 Node* const on_reject = Parameter(Descriptor::kOnReject);
881 Node* const exception = a.Parameter(Descriptor::kException); 828 Node* const exception = Parameter(Descriptor::kException);
882 Node* const context = a.Parameter(Descriptor::kContext); 829 Node* const context = Parameter(Descriptor::kContext);
883 Isolate* isolate = a.isolate(); 830
884 831 Callable call_callable = CodeFactory::Call(isolate());
885 Callable call_callable = CodeFactory::Call(isolate); 832 Variable var_unused(this, MachineRepresentation::kTagged);
886 Variable var_unused(&a, MachineRepresentation::kTagged); 833
887 834 Label if_internalhandler(this), if_customhandler(this, Label::kDeferred);
888 Label if_internalhandler(&a), if_customhandler(&a, Label::kDeferred); 835 Branch(IsUndefined(on_reject), &if_internalhandler, &if_customhandler);
889 a.Branch(a.IsUndefined(on_reject), &if_internalhandler, &if_customhandler); 836
890 837 Bind(&if_internalhandler);
891 a.Bind(&if_internalhandler); 838 {
892 { 839 CallRuntime(Runtime::kPromiseReject, context, promise, exception,
893 a.CallRuntime(Runtime::kPromiseReject, context, promise, exception, 840 FalseConstant());
894 a.FalseConstant()); 841 Return(UndefinedConstant());
895 a.Return(a.UndefinedConstant()); 842 }
896 } 843
897 844 Bind(&if_customhandler);
898 a.Bind(&if_customhandler); 845 {
899 { 846 CallJS(call_callable, context, on_reject, UndefinedConstant(), exception);
900 a.CallJS(call_callable, context, on_reject, a.UndefinedConstant(), 847 Return(UndefinedConstant());
901 exception); 848 }
902 a.Return(a.UndefinedConstant()); 849 }
903 } 850
904 } 851 TF_BUILTIN(PromiseHandle, PromiseBuiltinsAssembler) {
905 852 Node* const value = Parameter(2);
906 void Builtins::Generate_PromiseHandle(compiler::CodeAssemblerState* state) { 853 Node* const handler = Parameter(3);
907 CodeStubAssembler a(state); 854 Node* const deferred = Parameter(4);
908 typedef compiler::Node Node; 855 Node* const context = Parameter(7);
909 typedef CodeStubAssembler::Label Label; 856 Isolate* isolate = this->isolate();
910 typedef CodeStubAssembler::Variable Variable;
911
912 Node* const value = a.Parameter(2);
913 Node* const handler = a.Parameter(3);
914 Node* const deferred = a.Parameter(4);
915 Node* const context = a.Parameter(7);
916 Isolate* isolate = a.isolate();
917 857
918 // Get promise from deferred 858 // Get promise from deferred
919 // TODO(gsathya): Remove this lookup by getting rid of the deferred object. 859 // TODO(gsathya): Remove this lookup by getting rid of the deferred object.
920 Callable getproperty_callable = CodeFactory::GetProperty(isolate); 860 Callable getproperty_callable = CodeFactory::GetProperty(isolate);
921 Node* const key = a.HeapConstant(isolate->factory()->promise_string()); 861 Node* const key = HeapConstant(isolate->factory()->promise_string());
922 Node* const deferred_promise = 862 Node* const deferred_promise =
923 a.CallStub(getproperty_callable, context, deferred, key); 863 CallStub(getproperty_callable, context, deferred, key);
924 864
925 Variable var_reason(&a, MachineRepresentation::kTagged); 865 Variable var_reason(this, MachineRepresentation::kTagged);
926 866
927 Node* const is_debug_active = a.IsDebugActive(); 867 Node* const is_debug_active = IsDebugActive();
928 Label run_handler(&a), if_rejectpromise(&a), debug_push(&a, Label::kDeferred), 868 Label run_handler(this), if_rejectpromise(this),
929 debug_pop(&a, Label::kDeferred); 869 debug_push(this, Label::kDeferred), debug_pop(this, Label::kDeferred);
930 a.Branch(is_debug_active, &debug_push, &run_handler); 870 Branch(is_debug_active, &debug_push, &run_handler);
931 871
932 a.Bind(&debug_push); 872 Bind(&debug_push);
933 { 873 {
934 a.CallRuntime(Runtime::kDebugPushPromise, context, deferred_promise); 874 CallRuntime(Runtime::kDebugPushPromise, context, deferred_promise);
935 a.Goto(&run_handler); 875 Goto(&run_handler);
936 } 876 }
937 877
938 a.Bind(&run_handler); 878 Bind(&run_handler);
939 { 879 {
940 Callable call_callable = CodeFactory::Call(isolate); 880 Callable call_callable = CodeFactory::Call(isolate);
941 881
942 Node* const result = 882 Node* const result =
943 a.CallJS(call_callable, context, handler, a.UndefinedConstant(), value); 883 CallJS(call_callable, context, handler, UndefinedConstant(), value);
944 884
945 a.GotoIfException(result, &if_rejectpromise, &var_reason); 885 GotoIfException(result, &if_rejectpromise, &var_reason);
946 886
947 // TODO(gsathya): Remove this lookup by getting rid of the deferred object. 887 // TODO(gsathya): Remove this lookup by getting rid of the deferred object.
948 Node* const key = a.HeapConstant(isolate->factory()->resolve_string()); 888 Node* const key = HeapConstant(isolate->factory()->resolve_string());
949 Node* const on_resolve = 889 Node* const on_resolve =
950 a.CallStub(getproperty_callable, context, deferred, key); 890 CallStub(getproperty_callable, context, deferred, key);
951 891
952 Label if_internalhandler(&a), if_customhandler(&a, Label::kDeferred); 892 Label if_internalhandler(this), if_customhandler(this, Label::kDeferred);
953 a.Branch(a.IsUndefined(on_resolve), &if_internalhandler, &if_customhandler); 893 Branch(IsUndefined(on_resolve), &if_internalhandler, &if_customhandler);
954 894
955 a.Bind(&if_internalhandler); 895 Bind(&if_internalhandler);
956 InternalResolvePromise(&a, context, deferred_promise, result, &debug_pop); 896 InternalResolvePromise(context, deferred_promise, result, &debug_pop);
957 897
958 a.Bind(&if_customhandler); 898 Bind(&if_customhandler);
959 { 899 {
960 Node* const maybe_exception = a.CallJS(call_callable, context, on_resolve, 900 Node* const maybe_exception = CallJS(call_callable, context, on_resolve,
961 a.UndefinedConstant(), result); 901 UndefinedConstant(), result);
962 a.GotoIfException(maybe_exception, &if_rejectpromise, &var_reason); 902 GotoIfException(maybe_exception, &if_rejectpromise, &var_reason);
963 a.Goto(&debug_pop); 903 Goto(&debug_pop);
964 } 904 }
965 } 905 }
966 906
967 a.Bind(&if_rejectpromise); 907 Bind(&if_rejectpromise);
968 { 908 {
969 // TODO(gsathya): Remove this lookup by getting rid of the deferred object. 909 // TODO(gsathya): Remove this lookup by getting rid of the deferred object.
970 Node* const key = a.HeapConstant(isolate->factory()->reject_string()); 910 Node* const key = HeapConstant(isolate->factory()->reject_string());
971 Node* const on_reject = 911 Node* const on_reject =
972 a.CallStub(getproperty_callable, context, deferred, key); 912 CallStub(getproperty_callable, context, deferred, key);
973 913
974 Callable promise_handle_reject = CodeFactory::PromiseHandleReject(isolate); 914 Callable promise_handle_reject = CodeFactory::PromiseHandleReject(isolate);
975 a.CallStub(promise_handle_reject, context, deferred_promise, on_reject, 915 CallStub(promise_handle_reject, context, deferred_promise, on_reject,
976 var_reason.value()); 916 var_reason.value());
977 a.Goto(&debug_pop); 917 Goto(&debug_pop);
978 } 918 }
979 919
980 a.Bind(&debug_pop); 920 Bind(&debug_pop);
981 { 921 {
982 Label out(&a); 922 Label out(this);
983 923
984 a.GotoUnless(is_debug_active, &out); 924 GotoUnless(is_debug_active, &out);
985 a.CallRuntime(Runtime::kDebugPopPromise, context); 925 CallRuntime(Runtime::kDebugPopPromise, context);
986 a.Goto(&out); 926 Goto(&out);
987 927
988 a.Bind(&out); 928 Bind(&out);
989 a.Return(a.UndefinedConstant()); 929 Return(UndefinedConstant());
990 } 930 }
991 } 931 }
992 932
993 } // namespace internal 933 } // namespace internal
994 } // namespace v8 934 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698