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

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

Issue 2596553002: [promises] Move Promise.prototype.catch to TF (Closed)
Patch Set: fix nits 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-promise.h ('k') | src/js/promise.js » ('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-promise.h" 5 #include "src/builtins/builtins-promise.h"
6 #include "src/builtins/builtins-utils.h" 6 #include "src/builtins/builtins-utils.h"
7 #include "src/builtins/builtins.h" 7 #include "src/builtins/builtins.h"
8 #include "src/code-factory.h" 8 #include "src/code-factory.h"
9 #include "src/code-stub-assembler.h" 9 #include "src/code-stub-assembler.h"
10 #include "src/promise-utils.h" 10 #include "src/promise-utils.h"
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
173 Node* new_elements = AllocateFixedArray(kind, new_capacity, mode, flags); 173 Node* new_elements = AllocateFixedArray(kind, new_capacity, mode, flags);
174 174
175 CopyFixedArrayElements(kind, elements, new_elements, length, barrier_mode, 175 CopyFixedArrayElements(kind, elements, new_elements, length, barrier_mode,
176 mode); 176 mode);
177 StoreFixedArrayElement(new_elements, length, value, barrier_mode, 177 StoreFixedArrayElement(new_elements, length, value, barrier_mode,
178 additional_offset, mode); 178 additional_offset, mode);
179 179
180 StoreObjectField(promise, offset, new_elements); 180 StoreObjectField(promise, offset, new_elements);
181 } 181 }
182 182
183 Node* PromiseBuiltinsAssembler::InternalPromiseThen(Node* context,
184 Node* promise,
185 Node* on_resolve,
186 Node* on_reject) {
187 Isolate* isolate = this->isolate();
188
189 // 2. If IsPromise(promise) is false, throw a TypeError exception.
190 ThrowIfNotInstanceType(context, promise, JS_PROMISE_TYPE,
191 "Promise.prototype.then");
192
193 Node* const native_context = LoadNativeContext(context);
194 Node* const promise_fun =
195 LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
196
197 // 3. Let C be ? SpeciesConstructor(promise, %Promise%).
198 Node* constructor = SpeciesConstructor(context, promise, promise_fun);
199
200 // 4. Let resultCapability be ? NewPromiseCapability(C).
201 Callable call_callable = CodeFactory::Call(isolate);
202 Label fast_promise_capability(this), promise_capability(this),
203 perform_promise_then(this);
204 Variable var_deferred(this, MachineRepresentation::kTagged);
205
206 Branch(WordEqual(promise_fun, constructor), &fast_promise_capability,
207 &promise_capability);
208
209 // TODO(gsathya): Remove deferred object and move
210 // NewPromiseCapabability functions to TF.
211 Bind(&fast_promise_capability);
212 {
213 // TODO(gsathya): Move this to TF.
214 Node* const promise_internal_capability = LoadContextElement(
215 native_context, Context::INTERNAL_PROMISE_CAPABILITY_INDEX);
216 Node* const capability =
217 CallJS(call_callable, context, promise_internal_capability,
218 UndefinedConstant(), promise);
219 var_deferred.Bind(capability);
220 Goto(&perform_promise_then);
221 }
222
223 Bind(&promise_capability);
224 {
225 // TODO(gsathya): Move this to TF.
226 Node* const new_promise_capability = LoadContextElement(
227 native_context, Context::NEW_PROMISE_CAPABILITY_INDEX);
228 Node* const capability =
229 CallJS(call_callable, context, new_promise_capability,
230 UndefinedConstant(), constructor);
231 var_deferred.Bind(capability);
232 Goto(&perform_promise_then);
233 }
234
235 // 5. Return PerformPromiseThen(promise, onFulfilled, onRejected,
236 // resultCapability).
237 Bind(&perform_promise_then);
238 Node* const result = InternalPerformPromiseThen(
239 context, promise, on_resolve, on_reject, var_deferred.value());
240 return result;
241 }
242
183 Node* PromiseBuiltinsAssembler::InternalPerformPromiseThen(Node* context, 243 Node* PromiseBuiltinsAssembler::InternalPerformPromiseThen(Node* context,
184 Node* promise, 244 Node* promise,
185 Node* on_resolve, 245 Node* on_resolve,
186 Node* on_reject, 246 Node* on_reject,
187 Node* deferred) { 247 Node* deferred) {
188 Node* const native_context = LoadNativeContext(context); 248 Node* const native_context = LoadNativeContext(context);
189 249
190 Variable var_on_resolve(this, MachineRepresentation::kTagged), 250 Variable var_on_resolve(this, MachineRepresentation::kTagged),
191 var_on_reject(this, MachineRepresentation::kTagged); 251 var_on_reject(this, MachineRepresentation::kTagged);
192 252
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 LoadContextElement(native_context, Context::PROMISE_PROTOTYPE_MAP_INDEX); 431 LoadContextElement(native_context, Context::PROMISE_PROTOTYPE_MAP_INDEX);
372 Node* const proto_map = LoadMap(LoadMapPrototype(map)); 432 Node* const proto_map = LoadMap(LoadMapPrototype(map));
373 Node* const proto_has_initialmap = 433 Node* const proto_has_initialmap =
374 WordEqual(proto_map, initial_proto_initial_map); 434 WordEqual(proto_map, initial_proto_initial_map);
375 435
376 Branch(proto_has_initialmap, if_isunmodified, if_ismodified); 436 Branch(proto_has_initialmap, if_isunmodified, if_ismodified);
377 } 437 }
378 438
379 void PromiseBuiltinsAssembler::InternalResolvePromise(Node* context, 439 void PromiseBuiltinsAssembler::InternalResolvePromise(Node* context,
380 Node* promise, 440 Node* promise,
381 Node* result, 441 Node* result) {
382 Label* out) {
383 Isolate* isolate = this->isolate(); 442 Isolate* isolate = this->isolate();
384 443
385 Variable var_reason(this, MachineRepresentation::kTagged), 444 Variable var_reason(this, MachineRepresentation::kTagged),
386 var_then(this, MachineRepresentation::kTagged); 445 var_then(this, MachineRepresentation::kTagged);
387 446
388 Label do_enqueue(this), fulfill(this), if_cycle(this, Label::kDeferred), 447 Label do_enqueue(this), fulfill(this), if_cycle(this, Label::kDeferred),
389 if_rejectpromise(this, Label::kDeferred); 448 if_rejectpromise(this, Label::kDeferred), out(this);
390 449
391 Label cycle_check(this); 450 Label cycle_check(this);
392 GotoUnless(IsPromiseHookEnabled(), &cycle_check); 451 GotoUnless(IsPromiseHookEnabled(), &cycle_check);
393 CallRuntime(Runtime::kPromiseHookResolve, context, promise); 452 CallRuntime(Runtime::kPromiseHookResolve, context, promise);
394 Goto(&cycle_check); 453 Goto(&cycle_check);
395 454
396 Bind(&cycle_check); 455 Bind(&cycle_check);
397 // 6. If SameValue(resolution, promise) is true, then 456 // 6. If SameValue(resolution, promise) is true, then
398 GotoIf(SameValue(promise, result, context), &if_cycle); 457 GotoIf(SameValue(promise, result, context), &if_cycle);
399 458
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
431 { 490 {
432 Label if_fulfilled(this), if_rejected(this); 491 Label if_fulfilled(this), if_rejected(this);
433 Branch(SmiEqual(SmiConstant(v8::Promise::kFulfilled), thenable_status), 492 Branch(SmiEqual(SmiConstant(v8::Promise::kFulfilled), thenable_status),
434 &if_fulfilled, &if_rejected); 493 &if_fulfilled, &if_rejected);
435 494
436 Bind(&if_fulfilled); 495 Bind(&if_fulfilled);
437 { 496 {
438 CallRuntime(Runtime::kPromiseFulfill, context, promise, 497 CallRuntime(Runtime::kPromiseFulfill, context, promise,
439 SmiConstant(v8::Promise::kFulfilled), thenable_value); 498 SmiConstant(v8::Promise::kFulfilled), thenable_value);
440 PromiseSetHasHandler(promise); 499 PromiseSetHasHandler(promise);
441 Goto(out); 500 Goto(&out);
442 } 501 }
443 502
444 Bind(&if_rejected); 503 Bind(&if_rejected);
445 { 504 {
446 Label reject(this); 505 Label reject(this);
447 Node* const has_handler = PromiseHasHandler(result); 506 Node* const has_handler = PromiseHasHandler(result);
448 507
449 // Promise has already been rejected, but had no handler. 508 // Promise has already been rejected, but had no handler.
450 // Revoke previously triggered reject event. 509 // Revoke previously triggered reject event.
451 GotoIf(has_handler, &reject); 510 GotoIf(has_handler, &reject);
452 CallRuntime(Runtime::kPromiseRevokeReject, context, result); 511 CallRuntime(Runtime::kPromiseRevokeReject, context, result);
453 Goto(&reject); 512 Goto(&reject);
454 513
455 Bind(&reject); 514 Bind(&reject);
456 // Don't cause a debug event as this case is forwarding a rejection 515 // Don't cause a debug event as this case is forwarding a rejection
457 CallRuntime(Runtime::kPromiseReject, context, promise, thenable_value, 516 CallRuntime(Runtime::kPromiseReject, context, promise, thenable_value,
458 FalseConstant()); 517 FalseConstant());
459 PromiseSetHasHandler(result); 518 PromiseSetHasHandler(result);
460 Goto(out); 519 Goto(&out);
461 } 520 }
462 } 521 }
463 } 522 }
464 523
465 Bind(&if_notnativepromise); 524 Bind(&if_notnativepromise);
466 { 525 {
467 // 8. Let then be Get(resolution, "then"). 526 // 8. Let then be Get(resolution, "then").
468 Node* const then_str = HeapConstant(isolate->factory()->then_string()); 527 Node* const then_str = HeapConstant(isolate->factory()->then_string());
469 Callable getproperty_callable = CodeFactory::GetProperty(isolate); 528 Callable getproperty_callable = CodeFactory::GetProperty(isolate);
470 Node* const then = 529 Node* const then =
(...skipping 22 matching lines...) Expand all
493 CallRuntime(Runtime::kSetProperty, context, result, key, promise, 552 CallRuntime(Runtime::kSetProperty, context, result, key, promise,
494 SmiConstant(STRICT)); 553 SmiConstant(STRICT));
495 Goto(&enqueue); 554 Goto(&enqueue);
496 555
497 // 12. Perform EnqueueJob("PromiseJobs", 556 // 12. Perform EnqueueJob("PromiseJobs",
498 // PromiseResolveThenableJob, « promise, resolution, thenAction 557 // PromiseResolveThenableJob, « promise, resolution, thenAction
499 // »). 558 // »).
500 Bind(&enqueue); 559 Bind(&enqueue);
501 CallRuntime(Runtime::kEnqueuePromiseResolveThenableJob, context, promise, 560 CallRuntime(Runtime::kEnqueuePromiseResolveThenableJob, context, promise,
502 result, var_then.value()); 561 result, var_then.value());
503 Goto(out); 562 Goto(&out);
504 } 563 }
505 564
506 // 7.b Return FulfillPromise(promise, resolution). 565 // 7.b Return FulfillPromise(promise, resolution).
507 Bind(&fulfill); 566 Bind(&fulfill);
508 { 567 {
509 CallRuntime(Runtime::kPromiseFulfill, context, promise, 568 CallRuntime(Runtime::kPromiseFulfill, context, promise,
510 SmiConstant(v8::Promise::kFulfilled), result); 569 SmiConstant(v8::Promise::kFulfilled), result);
511 Goto(out); 570 Goto(&out);
512 } 571 }
513 572
514 Bind(&if_cycle); 573 Bind(&if_cycle);
515 { 574 {
516 // 6.a Let selfResolutionError be a newly created TypeError object. 575 // 6.a Let selfResolutionError be a newly created TypeError object.
517 Node* const message_id = SmiConstant(MessageTemplate::kPromiseCyclic); 576 Node* const message_id = SmiConstant(MessageTemplate::kPromiseCyclic);
518 Node* const error = 577 Node* const error =
519 CallRuntime(Runtime::kNewTypeError, context, message_id, result); 578 CallRuntime(Runtime::kNewTypeError, context, message_id, result);
520 var_reason.Bind(error); 579 var_reason.Bind(error);
521 580
522 // 6.b Return RejectPromise(promise, selfResolutionError). 581 // 6.b Return RejectPromise(promise, selfResolutionError).
523 Goto(&if_rejectpromise); 582 Goto(&if_rejectpromise);
524 } 583 }
525 584
526 // 9.a Return RejectPromise(promise, then.[[Value]]). 585 // 9.a Return RejectPromise(promise, then.[[Value]]).
527 Bind(&if_rejectpromise); 586 Bind(&if_rejectpromise);
528 { 587 {
529 CallRuntime(Runtime::kPromiseReject, context, promise, var_reason.value(), 588 CallRuntime(Runtime::kPromiseReject, context, promise, var_reason.value(),
530 TrueConstant()); 589 TrueConstant());
531 Goto(out); 590 Goto(&out);
532 } 591 }
592
593 Bind(&out);
533 } 594 }
534 595
535 // ES#sec-promise-reject-functions 596 // ES#sec-promise-reject-functions
536 // Promise Reject Functions 597 // Promise Reject Functions
537 BUILTIN(PromiseRejectClosure) { 598 BUILTIN(PromiseRejectClosure) {
538 HandleScope scope(isolate); 599 HandleScope scope(isolate);
539 600
540 Handle<Context> context(isolate->context(), isolate); 601 Handle<Context> context(isolate->context(), isolate);
541 602
542 if (PromiseUtils::HasAlreadyVisited(context)) { 603 if (PromiseUtils::HasAlreadyVisited(context)) {
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
755 Node* const deferred = Parameter(4); 816 Node* const deferred = Parameter(4);
756 Node* const context = Parameter(7); 817 Node* const context = Parameter(7);
757 818
758 Node* const result = InternalPerformPromiseThen(context, promise, on_resolve, 819 Node* const result = InternalPerformPromiseThen(context, promise, on_resolve,
759 on_reject, deferred); 820 on_reject, deferred);
760 821
761 // TODO(gsathya): This is unused, but value is returned according to spec. 822 // TODO(gsathya): This is unused, but value is returned according to spec.
762 Return(result); 823 Return(result);
763 } 824 }
764 825
826 // ES#sec-promise.prototype.then
827 // Promise.prototype.catch ( onFulfilled, onRejected )
765 TF_BUILTIN(PromiseThen, PromiseBuiltinsAssembler) { 828 TF_BUILTIN(PromiseThen, PromiseBuiltinsAssembler) {
766 // 1. Let promise be the this value. 829 // 1. Let promise be the this value.
767 Node* const promise = Parameter(0); 830 Node* const promise = Parameter(0);
768 Node* const on_resolve = Parameter(1); 831 Node* const on_resolve = Parameter(1);
769 Node* const on_reject = Parameter(2); 832 Node* const on_reject = Parameter(2);
770 Node* const context = Parameter(5); 833 Node* const context = Parameter(5);
771 Isolate* isolate = this->isolate();
772 834
773 // 2. If IsPromise(promise) is false, throw a TypeError exception. 835 Node* const result =
774 ThrowIfNotInstanceType(context, promise, JS_PROMISE_TYPE, 836 InternalPromiseThen(context, promise, on_resolve, on_reject);
775 "Promise.prototype.then");
776
777 Node* const native_context = LoadNativeContext(context);
778 Node* const promise_fun =
779 LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
780
781 // 3. Let C be ? SpeciesConstructor(promise, %Promise%).
782 Node* constructor = SpeciesConstructor(context, promise, promise_fun);
783
784 // 4. Let resultCapability be ? NewPromiseCapability(C).
785 Callable call_callable = CodeFactory::Call(isolate);
786 Label fast_promise_capability(this), promise_capability(this),
787 perform_promise_then(this);
788 Variable var_deferred(this, MachineRepresentation::kTagged);
789
790 Branch(WordEqual(promise_fun, constructor), &fast_promise_capability,
791 &promise_capability);
792
793 // TODO(gsathya): Remove deferred object and move
794 // NewPromiseCapabability functions to TF.
795 Bind(&fast_promise_capability);
796 {
797 // TODO(gsathya): Move this to TF.
798 Node* const promise_internal_capability = LoadContextElement(
799 native_context, Context::INTERNAL_PROMISE_CAPABILITY_INDEX);
800 Node* const capability =
801 CallJS(call_callable, context, promise_internal_capability,
802 UndefinedConstant(), promise);
803 var_deferred.Bind(capability);
804 Goto(&perform_promise_then);
805 }
806
807 Bind(&promise_capability);
808 {
809 // TODO(gsathya): Move this to TF.
810 Node* const new_promise_capability = LoadContextElement(
811 native_context, Context::NEW_PROMISE_CAPABILITY_INDEX);
812 Node* const capability =
813 CallJS(call_callable, context, new_promise_capability,
814 UndefinedConstant(), constructor);
815 var_deferred.Bind(capability);
816 Goto(&perform_promise_then);
817 }
818
819 // 5. Return PerformPromiseThen(promise, onFulfilled, onRejected,
820 // resultCapability).
821 Bind(&perform_promise_then);
822 Node* const result = InternalPerformPromiseThen(
823 context, promise, on_resolve, on_reject, var_deferred.value());
824 Return(result); 837 Return(result);
825 } 838 }
826 839
827 // ES#sec-promise-resolve-functions 840 // ES#sec-promise-resolve-functions
828 // Promise Resolve Functions 841 // Promise Resolve Functions
829 TF_BUILTIN(PromiseResolveClosure, PromiseBuiltinsAssembler) { 842 TF_BUILTIN(PromiseResolveClosure, PromiseBuiltinsAssembler) {
830 Node* const value = Parameter(1); 843 Node* const value = Parameter(1);
831 Node* const context = Parameter(4); 844 Node* const context = Parameter(4);
832 845
833 Label out(this); 846 Label out(this);
834 847
835 // 3. Let alreadyResolved be F.[[AlreadyResolved]]. 848 // 3. Let alreadyResolved be F.[[AlreadyResolved]].
836 Node* const has_already_visited_slot = 849 Node* const has_already_visited_slot =
837 IntPtrConstant(PromiseUtils::kAlreadyVisitedSlot); 850 IntPtrConstant(PromiseUtils::kAlreadyVisitedSlot);
838 851
839 Node* const has_already_visited = 852 Node* const has_already_visited =
840 LoadFixedArrayElement(context, has_already_visited_slot); 853 LoadFixedArrayElement(context, has_already_visited_slot);
841 854
842 // 4. If alreadyResolved.[[Value]] is true, return undefined. 855 // 4. If alreadyResolved.[[Value]] is true, return undefined.
843 GotoIf(SmiEqual(has_already_visited, SmiConstant(1)), &out); 856 GotoIf(SmiEqual(has_already_visited, SmiConstant(1)), &out);
844 857
845 // 5.Set alreadyResolved.[[Value]] to true. 858 // 5.Set alreadyResolved.[[Value]] to true.
846 StoreFixedArrayElement(context, has_already_visited_slot, SmiConstant(1)); 859 StoreFixedArrayElement(context, has_already_visited_slot, SmiConstant(1));
847 860
848 // 2. Let promise be F.[[Promise]]. 861 // 2. Let promise be F.[[Promise]].
849 Node* const promise = LoadFixedArrayElement( 862 Node* const promise = LoadFixedArrayElement(
850 context, IntPtrConstant(PromiseUtils::kPromiseSlot)); 863 context, IntPtrConstant(PromiseUtils::kPromiseSlot));
851 864
852 InternalResolvePromise(context, promise, value, &out); 865 InternalResolvePromise(context, promise, value);
866 Return(UndefinedConstant());
853 867
854 Bind(&out); 868 Bind(&out);
855 Return(UndefinedConstant()); 869 Return(UndefinedConstant());
856 } 870 }
857 871
858 TF_BUILTIN(ResolvePromise, PromiseBuiltinsAssembler) { 872 TF_BUILTIN(ResolvePromise, PromiseBuiltinsAssembler) {
859 Node* const promise = Parameter(1); 873 Node* const promise = Parameter(1);
860 Node* const result = Parameter(2); 874 Node* const result = Parameter(2);
861 Node* const context = Parameter(5); 875 Node* const context = Parameter(5);
862 876
863 Label out(this); 877 InternalResolvePromise(context, promise, result);
864 InternalResolvePromise(context, promise, result, &out);
865
866 Bind(&out);
867 Return(UndefinedConstant()); 878 Return(UndefinedConstant());
868 } 879 }
869 880
870 TF_BUILTIN(PromiseHandleReject, PromiseBuiltinsAssembler) { 881 TF_BUILTIN(PromiseHandleReject, PromiseBuiltinsAssembler) {
871 typedef PromiseHandleRejectDescriptor Descriptor; 882 typedef PromiseHandleRejectDescriptor Descriptor;
872 883
873 Node* const promise = Parameter(Descriptor::kPromise); 884 Node* const promise = Parameter(Descriptor::kPromise);
874 Node* const on_reject = Parameter(Descriptor::kOnReject); 885 Node* const on_reject = Parameter(Descriptor::kOnReject);
875 Node* const exception = Parameter(Descriptor::kException); 886 Node* const exception = Parameter(Descriptor::kException);
876 Node* const context = Parameter(Descriptor::kContext); 887 Node* const context = Parameter(Descriptor::kContext);
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
938 949
939 // TODO(gsathya): Remove this lookup by getting rid of the deferred object. 950 // TODO(gsathya): Remove this lookup by getting rid of the deferred object.
940 Node* const key = HeapConstant(isolate->factory()->resolve_string()); 951 Node* const key = HeapConstant(isolate->factory()->resolve_string());
941 Node* const on_resolve = 952 Node* const on_resolve =
942 CallStub(getproperty_callable, context, deferred, key); 953 CallStub(getproperty_callable, context, deferred, key);
943 954
944 Label if_internalhandler(this), if_customhandler(this, Label::kDeferred); 955 Label if_internalhandler(this), if_customhandler(this, Label::kDeferred);
945 Branch(IsUndefined(on_resolve), &if_internalhandler, &if_customhandler); 956 Branch(IsUndefined(on_resolve), &if_internalhandler, &if_customhandler);
946 957
947 Bind(&if_internalhandler); 958 Bind(&if_internalhandler);
948 InternalResolvePromise(context, deferred_promise, result, 959 InternalResolvePromise(context, deferred_promise, result);
949 &promisehook_after); 960 Goto(&promisehook_after);
950 961
951 Bind(&if_customhandler); 962 Bind(&if_customhandler);
952 { 963 {
953 Node* const maybe_exception = CallJS(call_callable, context, on_resolve, 964 Node* const maybe_exception = CallJS(call_callable, context, on_resolve,
954 UndefinedConstant(), result); 965 UndefinedConstant(), result);
955 GotoIfException(maybe_exception, &if_rejectpromise, &var_reason); 966 GotoIfException(maybe_exception, &if_rejectpromise, &var_reason);
956 Goto(&promisehook_after); 967 Goto(&promisehook_after);
957 } 968 }
958 } 969 }
959 970
(...skipping 23 matching lines...) Expand all
983 994
984 GotoUnless(is_debug_active, &out); 995 GotoUnless(is_debug_active, &out);
985 CallRuntime(Runtime::kDebugPopPromise, context); 996 CallRuntime(Runtime::kDebugPopPromise, context);
986 Goto(&out); 997 Goto(&out);
987 998
988 Bind(&out); 999 Bind(&out);
989 Return(UndefinedConstant()); 1000 Return(UndefinedConstant());
990 } 1001 }
991 } 1002 }
992 1003
1004 // ES#sec-promise.prototype.catch
1005 // Promise.prototype.catch ( onRejected )
1006 TF_BUILTIN(PromiseCatch, PromiseBuiltinsAssembler) {
1007 // 1. Let promise be the this value.
1008 Node* const promise = Parameter(0);
1009 Node* const on_resolve = UndefinedConstant();
1010 Node* const on_reject = Parameter(1);
1011 Node* const context = Parameter(4);
1012
1013 Label if_internalthen(this), if_customthen(this, Label::kDeferred);
1014 BranchIfFastPath(context, promise, &if_internalthen, &if_customthen);
1015
1016 Bind(&if_internalthen);
1017 {
1018 Node* const result =
1019 InternalPromiseThen(context, promise, on_resolve, on_reject);
1020 Return(result);
1021 }
1022
1023 Bind(&if_customthen);
1024 {
1025 Isolate* isolate = this->isolate();
1026 Node* const then_str = HeapConstant(isolate->factory()->then_string());
1027 Callable getproperty_callable = CodeFactory::GetProperty(isolate);
1028 Node* const then =
1029 CallStub(getproperty_callable, context, promise, then_str);
1030 Callable call_callable = CodeFactory::Call(isolate);
1031 Node* const result =
1032 CallJS(call_callable, context, then, promise, on_resolve, on_reject);
1033 Return(result);
1034 }
1035 }
1036
993 } // namespace internal 1037 } // namespace internal
994 } // namespace v8 1038 } // namespace v8
OLDNEW
« no previous file with comments | « src/builtins/builtins-promise.h ('k') | src/js/promise.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698