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

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

Issue 2554943002: Reland Create JSPromise (patchset #16 id:300001 of https://codereview.chromium.org/2536463002/ )" (Closed)
Patch Set: fix test 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 | « src/builtins/builtins.h ('k') | src/contexts.h » ('j') | 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
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 &resolve, &reject); 74 &resolve, &reject);
75 75
76 Handle<FixedArray> result = isolate->factory()->NewFixedArray(2); 76 Handle<FixedArray> result = isolate->factory()->NewFixedArray(2);
77 result->set(0, *resolve); 77 result->set(0, *resolve);
78 result->set(1, *reject); 78 result->set(1, *reject);
79 79
80 return *isolate->factory()->NewJSArrayWithElements(result, FAST_ELEMENTS, 2, 80 return *isolate->factory()->NewJSArrayWithElements(result, FAST_ELEMENTS, 2,
81 NOT_TENURED); 81 NOT_TENURED);
82 } 82 }
83 83
84 void PromiseInit(CodeStubAssembler* a, compiler::Node* promise,
85 compiler::Node* status, compiler::Node* result) {
86 CSA_ASSERT(a, a->TaggedIsSmi(status));
87 a->StoreObjectField(promise, JSPromise::kStatusOffset, status);
88 a->StoreObjectField(promise, JSPromise::kResultOffset, result);
89 }
90
84 void Builtins::Generate_PromiseConstructor( 91 void Builtins::Generate_PromiseConstructor(
85 compiler::CodeAssemblerState* state) { 92 compiler::CodeAssemblerState* state) {
86 CodeStubAssembler a(state); 93 CodeStubAssembler a(state);
87 typedef CodeStubAssembler::Variable Variable; 94 typedef CodeStubAssembler::Variable Variable;
88 typedef CodeStubAssembler::Label Label; 95 typedef CodeStubAssembler::Label Label;
89 typedef compiler::Node Node; 96 typedef compiler::Node Node;
90 97
91 Node* const executor = a.Parameter(1); 98 Node* const executor = a.Parameter(1);
92 Node* const new_target = a.Parameter(2); 99 Node* const new_target = a.Parameter(2);
93 Node* const context = a.Parameter(4); 100 Node* const context = a.Parameter(4);
94 Isolate* isolate = a.isolate(); 101 Isolate* isolate = a.isolate();
95 102
96 Label if_targetisundefined(&a, Label::kDeferred); 103 Label if_targetisundefined(&a, Label::kDeferred);
97 104
98 a.GotoIf(a.IsUndefined(new_target), &if_targetisundefined); 105 a.GotoIf(a.IsUndefined(new_target), &if_targetisundefined);
99 106
100 Label if_notcallable(&a, Label::kDeferred); 107 Label if_notcallable(&a, Label::kDeferred);
101 108
102 a.GotoIf(a.TaggedIsSmi(executor), &if_notcallable); 109 a.GotoIf(a.TaggedIsSmi(executor), &if_notcallable);
103 110
104 Node* const executor_map = a.LoadMap(executor); 111 Node* const executor_map = a.LoadMap(executor);
105 a.GotoUnless(a.IsCallableMap(executor_map), &if_notcallable); 112 a.GotoUnless(a.IsCallableMap(executor_map), &if_notcallable);
106 113
107 Node* const native_context = a.LoadNativeContext(context); 114 Node* const native_context = a.LoadNativeContext(context);
108 Node* const promise_fun = 115 Node* const promise_fun =
109 a.LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX); 116 a.LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
110 Node* const is_debug_active = a.IsDebugActive(); 117 Node* const is_debug_active = a.IsDebugActive();
118 Label if_targetisnotmodified(&a), if_targetismodified(&a, Label::kDeferred),
119 run_executor(&a), debug_push(&a, Label::kDeferred), init(&a);
111 120
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, 121 a.Branch(a.WordEqual(promise_fun, new_target), &if_targetisnotmodified,
115 &if_targetismodified); 122 &if_targetismodified);
116 123
117 Variable var_result(&a, MachineRepresentation::kTagged), 124 Variable var_result(&a, MachineRepresentation::kTagged),
118 var_reject_call(&a, MachineRepresentation::kTagged), 125 var_reject_call(&a, MachineRepresentation::kTagged),
119 var_reason(&a, MachineRepresentation::kTagged); 126 var_reason(&a, MachineRepresentation::kTagged);
120 127
121 a.Bind(&if_targetisnotmodified); 128 a.Bind(&if_targetisnotmodified);
122 { 129 {
123 Node* const initial_map = a.LoadObjectField( 130 Node* const initial_map = a.LoadObjectField(
124 promise_fun, JSFunction::kPrototypeOrInitialMapOffset); 131 promise_fun, JSFunction::kPrototypeOrInitialMapOffset);
125 132
126 Node* const instance = a.AllocateJSObjectFromMap(initial_map); 133 Node* const instance = a.AllocateJSObjectFromMap(initial_map);
127 var_result.Bind(instance); 134 var_result.Bind(instance);
128 a.Branch(is_debug_active, &debug_push, &run_executor); 135 a.Goto(&init);
129 } 136 }
130 137
131 a.Bind(&if_targetismodified); 138 a.Bind(&if_targetismodified);
132 { 139 {
133 Callable fast_new_object_stub = CodeFactory::FastNewObject(isolate); 140 Callable fast_new_object_stub = CodeFactory::FastNewObject(isolate);
134 Node* const instance = 141 Node* const instance =
135 a.CallStub(fast_new_object_stub, context, promise_fun, new_target); 142 a.CallStub(fast_new_object_stub, context, promise_fun, new_target);
136 143
137 var_result.Bind(instance); 144 var_result.Bind(instance);
145 a.Goto(&init);
146 }
147
148 a.Bind(&init);
149 {
150 PromiseInit(&a, var_result.value(), a.SmiConstant(kPromisePending),
151 a.UndefinedConstant());
138 a.Branch(is_debug_active, &debug_push, &run_executor); 152 a.Branch(is_debug_active, &debug_push, &run_executor);
139 } 153 }
140 154
141 a.Bind(&debug_push); 155 a.Bind(&debug_push);
142 { 156 {
143 a.CallRuntime(Runtime::kDebugPushPromise, context, var_result.value()); 157 a.CallRuntime(Runtime::kDebugPushPromise, context, var_result.value());
144 a.Goto(&run_executor); 158 a.Goto(&run_executor);
145 } 159 }
146 160
147 a.Bind(&run_executor); 161 a.Bind(&run_executor);
148 { 162 {
149 Label out(&a), if_rejectpromise(&a), debug_pop(&a, Label::kDeferred); 163 Label out(&a), if_rejectpromise(&a), debug_pop(&a, Label::kDeferred);
150 164
151 Node* const key = a.LoadRoot(Heap::kpromise_state_symbolRootIndex); 165 // TODO(gsathya): Move this to TF.
152 Node* const value = a.SmiConstant(kPromisePending);
153 Node* const language_mode = a.SmiConstant(STRICT);
154 // TODO(ishell): Use SetProperty stub once available.
155 a.CallRuntime(Runtime::kSetProperty, context, var_result.value(), key,
156 value, language_mode);
157 Node* const resolving_functions = a.CallRuntime( 166 Node* const resolving_functions = a.CallRuntime(
158 Runtime::kCreateResolvingFunctions, context, var_result.value()); 167 Runtime::kCreateResolvingFunctions, context, var_result.value());
159 Node* const resolve = 168 Node* const resolve =
160 a.LoadFixedArrayElement(resolving_functions, a.IntPtrConstant(0)); 169 a.LoadFixedArrayElement(resolving_functions, a.IntPtrConstant(0));
161 Node* const reject = 170 Node* const reject =
162 a.LoadFixedArrayElement(resolving_functions, a.IntPtrConstant(1)); 171 a.LoadFixedArrayElement(resolving_functions, a.IntPtrConstant(1));
163 Callable call_callable = CodeFactory::Call(isolate); 172 Callable call_callable = CodeFactory::Call(isolate);
164 173
165 Node* const maybe_exception = 174 Node* const maybe_exception =
166 a.CallJS(call_callable, context, executor, a.UndefinedConstant(), 175 a.CallJS(call_callable, context, executor, a.UndefinedConstant(),
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
209 typedef compiler::Node Node; 218 typedef compiler::Node Node;
210 CodeStubAssembler a(state); 219 CodeStubAssembler a(state);
211 220
212 Node* const context = a.Parameter(3); 221 Node* const context = a.Parameter(3);
213 Node* const native_context = a.LoadNativeContext(context); 222 Node* const native_context = a.LoadNativeContext(context);
214 Node* const promise_fun = 223 Node* const promise_fun =
215 a.LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX); 224 a.LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
216 Node* const initial_map = 225 Node* const initial_map =
217 a.LoadObjectField(promise_fun, JSFunction::kPrototypeOrInitialMapOffset); 226 a.LoadObjectField(promise_fun, JSFunction::kPrototypeOrInitialMapOffset);
218 Node* const instance = a.AllocateJSObjectFromMap(initial_map); 227 Node* const instance = a.AllocateJSObjectFromMap(initial_map);
228
229 PromiseInit(&a, instance, a.SmiConstant(kPromisePending),
230 a.UndefinedConstant());
219 a.Return(instance); 231 a.Return(instance);
220 } 232 }
221 233
234 void Builtins::Generate_PromiseCreateAndSet(
235 compiler::CodeAssemblerState* state) {
236 typedef compiler::Node Node;
237 CodeStubAssembler a(state);
238
239 Node* const status = a.Parameter(1);
240 Node* const result = a.Parameter(2);
241 Node* const context = a.Parameter(5);
242 Node* const native_context = a.LoadNativeContext(context);
243
244 Node* const promise_fun =
245 a.LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
246 Node* const initial_map =
247 a.LoadObjectField(promise_fun, JSFunction::kPrototypeOrInitialMapOffset);
248 Node* const instance = a.AllocateJSObjectFromMap(initial_map);
249
250 PromiseInit(&a, instance, status, result);
251 a.Return(instance);
252 }
253
254 namespace {
255
256 compiler::Node* ThrowIfNotJSReceiver(CodeStubAssembler* a, Isolate* isolate,
257 compiler::Node* context,
258 compiler::Node* value,
259 MessageTemplate::Template msg_template) {
260 typedef compiler::Node Node;
261 typedef CodeStubAssembler::Label Label;
262 typedef CodeStubAssembler::Variable Variable;
263
264 Label out(a), throw_exception(a, Label::kDeferred);
265 Variable var_value_map(a, MachineRepresentation::kTagged);
266
267 a->GotoIf(a->TaggedIsSmi(value), &throw_exception);
268
269 // Load the instance type of the {value}.
270 var_value_map.Bind(a->LoadMap(value));
271 Node* const value_instance_type =
272 a->LoadMapInstanceType(var_value_map.value());
273
274 a->Branch(a->IsJSReceiverInstanceType(value_instance_type), &out,
275 &throw_exception);
276
277 // The {value} is not a compatible receiver for this method.
278 a->Bind(&throw_exception);
279 {
280 Node* const message_id = a->SmiConstant(msg_template);
281 a->CallRuntime(Runtime::kThrowTypeError, context, message_id);
282 var_value_map.Bind(a->UndefinedConstant());
283 a->Goto(&out); // Never reached.
284 }
285
286 a->Bind(&out);
287 return var_value_map.value();
288 }
289 } // namespace
290
222 void Builtins::Generate_IsPromise(compiler::CodeAssemblerState* state) { 291 void Builtins::Generate_IsPromise(compiler::CodeAssemblerState* state) {
223 CodeStubAssembler a(state); 292 CodeStubAssembler a(state);
224 typedef compiler::Node Node; 293 typedef compiler::Node Node;
225 typedef CodeStubAssembler::Label Label; 294 typedef CodeStubAssembler::Label Label;
226 295
227 Node* const maybe_promise = a.Parameter(1); 296 Node* const maybe_promise = a.Parameter(1);
228 Label if_ispromise(&a), if_isnotpromise(&a, Label::kDeferred); 297 Label if_notpromise(&a, Label::kDeferred);
229 a.GotoIf(a.TaggedIsSmi(maybe_promise), &if_isnotpromise); 298
230 299 a.GotoIf(a.TaggedIsSmi(maybe_promise), &if_notpromise);
231 a.Branch(a.HasInstanceType(maybe_promise, JS_PROMISE_TYPE), &if_ispromise, 300
232 &if_isnotpromise); 301 Node* const result = a.SelectBooleanConstant(
233 302 a.HasInstanceType(maybe_promise, JS_PROMISE_TYPE));
234 a.Bind(&if_ispromise); 303 a.Return(result);
235 a.Return(a.BooleanConstant(true)); 304
236 305 a.Bind(&if_notpromise);
237 a.Bind(&if_isnotpromise); 306 a.Return(a.FalseConstant());
238 a.Return(a.BooleanConstant(false)); 307 }
308
309 namespace {
310 compiler::Node* SpeciesConstructor(CodeStubAssembler* a, Isolate* isolate,
311 compiler::Node* context,
312 compiler::Node* object,
313 compiler::Node* default_constructor) {
314 typedef compiler::Node Node;
315 typedef CodeStubAssembler::Label Label;
316 typedef CodeStubAssembler::Variable Variable;
317
318 Variable var_result(a, MachineRepresentation::kTagged);
319 var_result.Bind(default_constructor);
320
321 // 2. Let C be ? Get(O, "constructor").
322 Node* const constructor_str =
323 a->HeapConstant(isolate->factory()->constructor_string());
324 Callable getproperty_callable = CodeFactory::GetProperty(a->isolate());
325 Node* const constructor =
326 a->CallStub(getproperty_callable, context, object, constructor_str);
327
328 // 3. If C is undefined, return defaultConstructor.
329 Label out(a);
330 a->GotoIf(a->IsUndefined(constructor), &out);
331
332 // 4. If Type(C) is not Object, throw a TypeError exception.
333 ThrowIfNotJSReceiver(a, a->isolate(), context, constructor,
334 MessageTemplate::kConstructorNotReceiver);
335
336 // 5. Let S be ? Get(C, @@species).
337 Node* const species_symbol =
338 a->HeapConstant(isolate->factory()->species_symbol());
339 Node* const species =
340 a->CallStub(getproperty_callable, context, constructor, species_symbol);
341
342 // 6. If S is either undefined or null, return defaultConstructor.
343 a->GotoIf(a->IsUndefined(species), &out);
344 a->GotoIf(a->WordEqual(species, a->NullConstant()), &out);
345
346 // 7. If IsConstructor(S) is true, return S.
347 Label throw_error(a);
348 Node* species_bitfield = a->LoadMapBitField(a->LoadMap(species));
349 a->GotoUnless(
350 a->Word32Equal(a->Word32And(species_bitfield,
351 a->Int32Constant((1 << Map::kIsConstructor))),
352 a->Int32Constant(1 << Map::kIsConstructor)),
353 &throw_error);
354 var_result.Bind(species);
355 a->Goto(&out);
356
357 // 8. Throw a TypeError exception.
358 a->Bind(&throw_error);
359 {
360 Node* const message_id =
361 a->SmiConstant(MessageTemplate::kSpeciesNotConstructor);
362 a->CallRuntime(Runtime::kThrowTypeError, context, message_id);
363 a->Goto(&out);
364 }
365
366 a->Bind(&out);
367 return var_result.value();
368 }
369
370 void AppendPromiseCallback(CodeStubAssembler* a, int offset,
371 compiler::Node* promise, compiler::Node* value) {
372 typedef compiler::Node Node;
373
374 Node* elements = a->LoadObjectField(promise, offset);
375 Node* length = a->LoadFixedArrayBaseLength(elements);
376 CodeStubAssembler::ParameterMode mode = a->OptimalParameterMode();
377 length = a->UntagParameter(length, mode);
378
379 Node* delta = a->IntPtrOrSmiConstant(1, mode);
380 Node* new_capacity = a->IntPtrAdd(length, delta);
381 ElementsKind kind = FAST_ELEMENTS;
382
383 Node* new_elements = a->AllocateFixedArray(kind, new_capacity, mode);
384
385 a->CopyFixedArrayElements(kind, elements, new_elements, length,
386 UPDATE_WRITE_BARRIER, mode);
387 a->StoreFixedArrayElement(new_elements, length, value, UPDATE_WRITE_BARRIER,
388 0, mode);
389
390 a->StoreObjectField(promise, offset, new_elements);
391 }
392
393 compiler::Node* InternalPerformPromiseThen(CodeStubAssembler* a,
394 compiler::Node* context,
395 compiler::Node* promise,
396 compiler::Node* on_resolve,
397 compiler::Node* on_reject,
398 compiler::Node* deferred) {
399 typedef CodeStubAssembler::Variable Variable;
400 typedef CodeStubAssembler::Label Label;
401 typedef compiler::Node Node;
402
403 Isolate* isolate = a->isolate();
404 Node* const native_context = a->LoadNativeContext(context);
405
406 Variable var_on_resolve(a, MachineRepresentation::kTagged),
407 var_on_reject(a, MachineRepresentation::kTagged);
408
409 var_on_resolve.Bind(on_resolve);
410 var_on_reject.Bind(on_reject);
411
412 Label out(a), if_onresolvenotcallable(a), onrejectcheck(a),
413 append_callbacks(a);
414 a->GotoIf(a->TaggedIsSmi(on_resolve), &if_onresolvenotcallable);
415
416 Node* const on_resolve_map = a->LoadMap(on_resolve);
417 a->Branch(a->IsCallableMap(on_resolve_map), &onrejectcheck,
418 &if_onresolvenotcallable);
419
420 a->Bind(&if_onresolvenotcallable);
421 {
422 var_on_resolve.Bind(a->LoadContextElement(
423 native_context, Context::PROMISE_ID_RESOLVE_HANDLER_INDEX));
424 a->Goto(&onrejectcheck);
425 }
426
427 a->Bind(&onrejectcheck);
428 {
429 Label if_onrejectnotcallable(a);
430 a->GotoIf(a->TaggedIsSmi(on_reject), &if_onrejectnotcallable);
431
432 Node* const on_reject_map = a->LoadMap(on_reject);
433 a->Branch(a->IsCallableMap(on_reject_map), &append_callbacks,
434 &if_onrejectnotcallable);
435
436 a->Bind(&if_onrejectnotcallable);
437 {
438 var_on_reject.Bind(a->LoadContextElement(
439 native_context, Context::PROMISE_ID_REJECT_HANDLER_INDEX));
440 a->Goto(&append_callbacks);
441 }
442 }
443
444 a->Bind(&append_callbacks);
445 {
446 Label fulfilled_check(a);
447 Node* const status = a->LoadObjectField(promise, JSPromise::kStatusOffset);
448 a->GotoUnless(a->SmiEqual(status, a->SmiConstant(kPromisePending)),
449 &fulfilled_check);
450
451 Node* const existing_deferred =
452 a->LoadObjectField(promise, JSPromise::kDeferredOffset);
453
454 Label if_noexistingcallbacks(a), if_existingcallbacks(a);
455 a->Branch(a->IsUndefined(existing_deferred), &if_noexistingcallbacks,
456 &if_existingcallbacks);
457
458 a->Bind(&if_noexistingcallbacks);
459 {
460 // Store callbacks directly in the slots.
461 a->StoreObjectField(promise, JSPromise::kDeferredOffset, deferred);
462 a->StoreObjectField(promise, JSPromise::kFulfillReactionsOffset,
463 var_on_resolve.value());
464 a->StoreObjectField(promise, JSPromise::kRejectReactionsOffset,
465 var_on_reject.value());
466 a->Goto(&out);
467 }
468
469 a->Bind(&if_existingcallbacks);
470 {
471 Label if_singlecallback(a), if_multiplecallbacks(a);
472 a->BranchIfJSObject(existing_deferred, &if_singlecallback,
473 &if_multiplecallbacks);
474
475 a->Bind(&if_singlecallback);
476 {
477 // Create new FixedArrays to store callbacks.
478 Node* const deferreds =
479 a->AllocateFixedArray(FAST_ELEMENTS, a->Int32Constant(2));
480 Node* const fulfill_reactions =
481 a->AllocateFixedArray(FAST_ELEMENTS, a->Int32Constant(2));
482 Node* const reject_reactions =
483 a->AllocateFixedArray(FAST_ELEMENTS, a->Int32Constant(2));
484
485 // Store existing callbacks in FixedArrays.
486 a->StoreFixedArrayElement(deferreds, 0, existing_deferred);
487 a->StoreFixedArrayElement(
488 fulfill_reactions, 0,
489 a->LoadObjectField(promise, JSPromise::kFulfillReactionsOffset));
490 a->StoreFixedArrayElement(
491 reject_reactions, 0,
492 a->LoadObjectField(promise, JSPromise::kRejectReactionsOffset));
493
494 // Store new callbacks in FixedArrays.
495 a->StoreFixedArrayElement(deferreds, 1, deferred);
496 a->StoreFixedArrayElement(fulfill_reactions, 1, var_on_resolve.value());
497 a->StoreFixedArrayElement(reject_reactions, 1, var_on_reject.value());
498
499 // Store new FixedArrays in promise.
500 a->StoreObjectField(promise, JSPromise::kDeferredOffset, deferreds);
501 a->StoreObjectField(promise, JSPromise::kFulfillReactionsOffset,
502 fulfill_reactions);
503 a->StoreObjectField(promise, JSPromise::kRejectReactionsOffset,
504 reject_reactions);
505 a->Goto(&out);
506 }
507
508 a->Bind(&if_multiplecallbacks);
509 {
510 AppendPromiseCallback(a, JSPromise::kDeferredOffset, promise, deferred);
511 AppendPromiseCallback(a, JSPromise::kFulfillReactionsOffset, promise,
512 var_on_resolve.value());
513 AppendPromiseCallback(a, JSPromise::kRejectReactionsOffset, promise,
514 var_on_reject.value());
515 a->Goto(&out);
516 }
517 }
518
519 a->Bind(&fulfilled_check);
520 {
521 Label reject(a);
522 Node* const result =
523 a->LoadObjectField(promise, JSPromise::kResultOffset);
524 a->GotoUnless(a->WordEqual(status, a->SmiConstant(kPromiseFulfilled)),
525 &reject);
526
527 // TODO(gsathya): Move this to TF.
528 a->CallRuntime(Runtime::kEnqueuePromiseReactionJob, context, result,
529 var_on_resolve.value(), deferred,
530 a->SmiConstant(kPromiseFulfilled));
531 a->Goto(&out);
532
533 a->Bind(&reject);
534 {
535 Callable getproperty_callable = CodeFactory::GetProperty(isolate);
536 Node* const key =
537 a->HeapConstant(isolate->factory()->promise_has_handler_symbol());
538 Node* const has_handler =
539 a->CallStub(getproperty_callable, context, promise, key);
540
541 Label enqueue(a);
542
543 // TODO(gsathya): Fold these runtime calls and move to TF.
544 a->GotoIf(a->WordEqual(has_handler, a->TrueConstant()), &enqueue);
545 a->CallRuntime(Runtime::kPromiseRevokeReject, context, promise);
546 a->Goto(&enqueue);
547
548 a->Bind(&enqueue);
549 {
550 a->CallRuntime(Runtime::kEnqueuePromiseReactionJob, context, result,
551 var_on_reject.value(), deferred,
552 a->SmiConstant(kPromiseRejected));
553
554 a->Goto(&out);
555 }
556 }
557 }
558 }
559
560 a->Bind(&out);
561 // TODO(gsathya): Protect with debug check.
562 a->CallRuntime(
563 Runtime::kSetProperty, context, promise,
564 a->HeapConstant(isolate->factory()->promise_has_handler_symbol()),
565 a->TrueConstant(), a->SmiConstant(STRICT));
566
567 // TODO(gsathya): This call will be removed once we don't have to
568 // deal with deferred objects.
569 Callable getproperty_callable = CodeFactory::GetProperty(isolate);
570 Node* const key =
571 a->HeapConstant(isolate->factory()->NewStringFromAsciiChecked("promise"));
572 Node* const result =
573 a->CallStub(getproperty_callable, context, deferred, key);
574
575 return result;
576 }
577
578 } // namespace
579
580 void Builtins::Generate_PerformPromiseThen(
581 compiler::CodeAssemblerState* state) {
582 CodeStubAssembler a(state);
583 typedef compiler::Node Node;
584
585 Node* const promise = a.Parameter(1);
586 Node* const on_resolve = a.Parameter(2);
587 Node* const on_reject = a.Parameter(3);
588 Node* const deferred = a.Parameter(4);
589 Node* const context = a.Parameter(7);
590
591 Node* const result = InternalPerformPromiseThen(
592 &a, context, promise, on_resolve, on_reject, deferred);
593
594 // TODO(gsathya): This is unused, but value is returned according to spec.
595 a.Return(result);
596 }
597
598 void Builtins::Generate_PromiseThen(compiler::CodeAssemblerState* state) {
599 CodeStubAssembler a(state);
600 typedef compiler::Node Node;
601 typedef CodeStubAssembler::Label Label;
602 typedef CodeStubAssembler::Variable Variable;
603
604 // 1. Let promise be the this value.
605 Node* const promise = a.Parameter(0);
606 Node* const on_resolve = a.Parameter(1);
607 Node* const on_reject = a.Parameter(2);
608 Node* const context = a.Parameter(5);
609 Isolate* isolate = a.isolate();
610
611 // 2. If IsPromise(promise) is false, throw a TypeError exception.
612 a.ThrowIfNotInstanceType(context, promise, JS_PROMISE_TYPE,
613 "Promise.prototype.then");
614
615 Node* const native_context = a.LoadNativeContext(context);
616 Node* const promise_fun =
617 a.LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
618
619 // 3. Let C be ? SpeciesConstructor(promise, %Promise%).
620 Node* constructor =
621 SpeciesConstructor(&a, isolate, context, promise, promise_fun);
622
623 // 4. Let resultCapability be ? NewPromiseCapability(C).
624 Callable call_callable = CodeFactory::Call(isolate);
625 Label fast_promise_capability(&a), promise_capability(&a),
626 perform_promise_then(&a);
627 Variable var_deferred(&a, MachineRepresentation::kTagged);
628
629 a.Branch(a.WordEqual(promise_fun, constructor), &fast_promise_capability,
630 &promise_capability);
631
632 // TODO(gsathya): Remove deferred object and move
633 // NewPromiseCapbability functions to TF.
634 a.Bind(&fast_promise_capability);
635 {
636 // TODO(gsathya): Move this to TF.
637 Node* const promise_internal_capability = a.LoadContextElement(
638 native_context, Context::INTERNAL_PROMISE_CAPABILITY_INDEX);
639 Node* const capability =
640 a.CallJS(call_callable, context, promise_internal_capability,
641 a.UndefinedConstant());
642 var_deferred.Bind(capability);
643 a.Goto(&perform_promise_then);
644 }
645
646 a.Bind(&promise_capability);
647 {
648 // TODO(gsathya): Move this to TF.
649 Node* const new_promise_capability = a.LoadContextElement(
650 native_context, Context::NEW_PROMISE_CAPABILITY_INDEX);
651 Node* const capability =
652 a.CallJS(call_callable, context, new_promise_capability,
653 a.UndefinedConstant(), constructor);
654 var_deferred.Bind(capability);
655 a.Goto(&perform_promise_then);
656 }
657
658 // 5. Return PerformPromiseThen(promise, onFulfilled, onRejected,
659 // resultCapability).
660 a.Bind(&perform_promise_then);
661 Node* const result = InternalPerformPromiseThen(
662 &a, context, promise, on_resolve, on_reject, var_deferred.value());
663 a.Return(result);
239 } 664 }
240 665
241 } // namespace internal 666 } // namespace internal
242 } // namespace v8 667 } // namespace v8
OLDNEW
« no previous file with comments | « src/builtins/builtins.h ('k') | src/contexts.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698