OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/builtins/builtins-utils.h" | 5 #include "src/builtins/builtins-utils.h" |
6 #include "src/builtins/builtins.h" | 6 #include "src/builtins/builtins.h" |
7 #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 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
364 Node* result, | 364 Node* result, |
365 Label* out) { | 365 Label* out) { |
366 Isolate* isolate = this->isolate(); | 366 Isolate* isolate = this->isolate(); |
367 | 367 |
368 Variable var_reason(this, MachineRepresentation::kTagged), | 368 Variable var_reason(this, MachineRepresentation::kTagged), |
369 var_then(this, MachineRepresentation::kTagged); | 369 var_then(this, MachineRepresentation::kTagged); |
370 | 370 |
371 Label do_enqueue(this), fulfill(this), if_cycle(this, Label::kDeferred), | 371 Label do_enqueue(this), fulfill(this), if_cycle(this, Label::kDeferred), |
372 if_rejectpromise(this, Label::kDeferred); | 372 if_rejectpromise(this, Label::kDeferred); |
373 | 373 |
| 374 Label cycle_check(this); |
| 375 GotoUnless(IsPromiseHookEnabled(), &cycle_check); |
| 376 CallRuntime(Runtime::kPromiseHookResolve, context, promise); |
| 377 Goto(&cycle_check); |
| 378 |
| 379 Bind(&cycle_check); |
374 // 6. If SameValue(resolution, promise) is true, then | 380 // 6. If SameValue(resolution, promise) is true, then |
375 GotoIf(SameValue(promise, result, context), &if_cycle); | 381 GotoIf(SameValue(promise, result, context), &if_cycle); |
376 | 382 |
377 // 7. If Type(resolution) is not Object, then | 383 // 7. If Type(resolution) is not Object, then |
378 GotoIf(TaggedIsSmi(result), &fulfill); | 384 GotoIf(TaggedIsSmi(result), &fulfill); |
379 GotoUnless(IsJSReceiver(result), &fulfill); | 385 GotoUnless(IsJSReceiver(result), &fulfill); |
380 | 386 |
381 Label if_nativepromise(this), if_notnativepromise(this, Label::kDeferred); | 387 Label if_nativepromise(this), if_notnativepromise(this, Label::kDeferred); |
382 BranchIfFastPath(context, result, &if_nativepromise, &if_notnativepromise); | 388 BranchIfFastPath(context, result, &if_nativepromise, &if_notnativepromise); |
383 | 389 |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
584 &if_targetismodified); | 590 &if_targetismodified); |
585 | 591 |
586 Variable var_result(this, MachineRepresentation::kTagged), | 592 Variable var_result(this, MachineRepresentation::kTagged), |
587 var_reject_call(this, MachineRepresentation::kTagged), | 593 var_reject_call(this, MachineRepresentation::kTagged), |
588 var_reason(this, MachineRepresentation::kTagged); | 594 var_reason(this, MachineRepresentation::kTagged); |
589 | 595 |
590 Bind(&if_targetisnotmodified); | 596 Bind(&if_targetisnotmodified); |
591 { | 597 { |
592 Node* const instance = AllocateJSPromise(context); | 598 Node* const instance = AllocateJSPromise(context); |
593 var_result.Bind(instance); | 599 var_result.Bind(instance); |
| 600 GotoUnless(IsPromiseHookEnabled(), &init); |
| 601 CallRuntime(Runtime::kPromiseHookInit, context, instance, |
| 602 UndefinedConstant()); |
594 Goto(&init); | 603 Goto(&init); |
595 } | 604 } |
596 | 605 |
597 Bind(&if_targetismodified); | 606 Bind(&if_targetismodified); |
598 { | 607 { |
599 Callable fast_new_object_stub = CodeFactory::FastNewObject(isolate); | 608 Callable fast_new_object_stub = CodeFactory::FastNewObject(isolate); |
600 Node* const instance = | 609 Node* const instance = |
601 CallStub(fast_new_object_stub, context, promise_fun, new_target); | 610 CallStub(fast_new_object_stub, context, promise_fun, new_target); |
602 | 611 |
603 var_result.Bind(instance); | 612 var_result.Bind(instance); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
664 Bind(&if_notcallable); | 673 Bind(&if_notcallable); |
665 { | 674 { |
666 Node* const message_id = | 675 Node* const message_id = |
667 SmiConstant(MessageTemplate::kResolverNotAFunction); | 676 SmiConstant(MessageTemplate::kResolverNotAFunction); |
668 CallRuntime(Runtime::kThrowTypeError, context, message_id, executor); | 677 CallRuntime(Runtime::kThrowTypeError, context, message_id, executor); |
669 Return(UndefinedConstant()); // Never reached. | 678 Return(UndefinedConstant()); // Never reached. |
670 } | 679 } |
671 } | 680 } |
672 | 681 |
673 TF_BUILTIN(PromiseInternalConstructor, PromiseBuiltinsAssembler) { | 682 TF_BUILTIN(PromiseInternalConstructor, PromiseBuiltinsAssembler) { |
674 Node* const context = Parameter(3); | 683 Node* const parent = Parameter(1); |
| 684 Node* const context = Parameter(4); |
675 Node* const instance = AllocateJSPromise(context); | 685 Node* const instance = AllocateJSPromise(context); |
676 PromiseInit(instance); | 686 PromiseInit(instance); |
| 687 |
| 688 Label out(this); |
| 689 GotoUnless(IsPromiseHookEnabled(), &out); |
| 690 CallRuntime(Runtime::kPromiseHookInit, context, instance, parent); |
| 691 Goto(&out); |
| 692 Bind(&out); |
| 693 |
677 Return(instance); | 694 Return(instance); |
678 } | 695 } |
679 | 696 |
680 TF_BUILTIN(PromiseCreateAndSet, PromiseBuiltinsAssembler) { | 697 TF_BUILTIN(PromiseCreateAndSet, PromiseBuiltinsAssembler) { |
681 Node* const status = Parameter(1); | 698 Node* const status = Parameter(1); |
682 Node* const result = Parameter(2); | 699 Node* const result = Parameter(2); |
683 Node* const context = Parameter(5); | 700 Node* const context = Parameter(5); |
684 | 701 |
685 Node* const instance = AllocateJSPromise(context); | 702 Node* const instance = AllocateJSPromise(context); |
686 PromiseSet(instance, status, result); | 703 PromiseSet(instance, status, result); |
| 704 |
| 705 Label out(this); |
| 706 GotoUnless(IsPromiseHookEnabled(), &out); |
| 707 CallRuntime(Runtime::kPromiseHookInit, context, instance, |
| 708 UndefinedConstant()); |
| 709 Goto(&out); |
| 710 Bind(&out); |
687 Return(instance); | 711 Return(instance); |
688 } | 712 } |
689 | 713 |
690 TF_BUILTIN(IsPromise, PromiseBuiltinsAssembler) { | 714 TF_BUILTIN(IsPromise, PromiseBuiltinsAssembler) { |
691 Node* const maybe_promise = Parameter(1); | 715 Node* const maybe_promise = Parameter(1); |
692 Label if_notpromise(this, Label::kDeferred); | 716 Label if_notpromise(this, Label::kDeferred); |
693 | 717 |
694 GotoIf(TaggedIsSmi(maybe_promise), &if_notpromise); | 718 GotoIf(TaggedIsSmi(maybe_promise), &if_notpromise); |
695 | 719 |
696 Node* const result = | 720 Node* const result = |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
745 | 769 |
746 // TODO(gsathya): Remove deferred object and move | 770 // TODO(gsathya): Remove deferred object and move |
747 // NewPromiseCapabability functions to TF. | 771 // NewPromiseCapabability functions to TF. |
748 Bind(&fast_promise_capability); | 772 Bind(&fast_promise_capability); |
749 { | 773 { |
750 // TODO(gsathya): Move this to TF. | 774 // TODO(gsathya): Move this to TF. |
751 Node* const promise_internal_capability = LoadContextElement( | 775 Node* const promise_internal_capability = LoadContextElement( |
752 native_context, Context::INTERNAL_PROMISE_CAPABILITY_INDEX); | 776 native_context, Context::INTERNAL_PROMISE_CAPABILITY_INDEX); |
753 Node* const capability = | 777 Node* const capability = |
754 CallJS(call_callable, context, promise_internal_capability, | 778 CallJS(call_callable, context, promise_internal_capability, |
755 UndefinedConstant()); | 779 UndefinedConstant(), promise); |
756 var_deferred.Bind(capability); | 780 var_deferred.Bind(capability); |
757 Goto(&perform_promise_then); | 781 Goto(&perform_promise_then); |
758 } | 782 } |
759 | 783 |
760 Bind(&promise_capability); | 784 Bind(&promise_capability); |
761 { | 785 { |
762 // TODO(gsathya): Move this to TF. | 786 // TODO(gsathya): Move this to TF. |
763 Node* const new_promise_capability = LoadContextElement( | 787 Node* const new_promise_capability = LoadContextElement( |
764 native_context, Context::NEW_PROMISE_CAPABILITY_INDEX); | 788 native_context, Context::NEW_PROMISE_CAPABILITY_INDEX); |
765 Node* const capability = | 789 Node* const capability = |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
842 } | 866 } |
843 | 867 |
844 Bind(&if_customhandler); | 868 Bind(&if_customhandler); |
845 { | 869 { |
846 CallJS(call_callable, context, on_reject, UndefinedConstant(), exception); | 870 CallJS(call_callable, context, on_reject, UndefinedConstant(), exception); |
847 Return(UndefinedConstant()); | 871 Return(UndefinedConstant()); |
848 } | 872 } |
849 } | 873 } |
850 | 874 |
851 TF_BUILTIN(PromiseHandle, PromiseBuiltinsAssembler) { | 875 TF_BUILTIN(PromiseHandle, PromiseBuiltinsAssembler) { |
| 876 Node* const promise = Parameter(1); |
852 Node* const value = Parameter(2); | 877 Node* const value = Parameter(2); |
853 Node* const handler = Parameter(3); | 878 Node* const handler = Parameter(3); |
854 Node* const deferred = Parameter(4); | 879 Node* const deferred = Parameter(4); |
855 Node* const context = Parameter(7); | 880 Node* const context = Parameter(7); |
856 Isolate* isolate = this->isolate(); | 881 Isolate* isolate = this->isolate(); |
857 | 882 |
858 // Get promise from deferred | 883 // Get promise from deferred |
859 // TODO(gsathya): Remove this lookup by getting rid of the deferred object. | 884 // TODO(gsathya): Remove this lookup by getting rid of the deferred object. |
860 Callable getproperty_callable = CodeFactory::GetProperty(isolate); | 885 Callable getproperty_callable = CodeFactory::GetProperty(isolate); |
861 Node* const key = HeapConstant(isolate->factory()->promise_string()); | 886 Node* const key = HeapConstant(isolate->factory()->promise_string()); |
862 Node* const deferred_promise = | 887 Node* const deferred_promise = |
863 CallStub(getproperty_callable, context, deferred, key); | 888 CallStub(getproperty_callable, context, deferred, key); |
864 | 889 |
865 Variable var_reason(this, MachineRepresentation::kTagged); | 890 Variable var_reason(this, MachineRepresentation::kTagged); |
866 | 891 |
867 Node* const is_debug_active = IsDebugActive(); | 892 Node* const is_debug_active = IsDebugActive(); |
868 Label run_handler(this), if_rejectpromise(this), | 893 Label run_handler(this), if_rejectpromise(this), promisehook_before(this), |
869 debug_push(this, Label::kDeferred), debug_pop(this, Label::kDeferred); | 894 promisehook_after(this), debug_pop(this); |
870 Branch(is_debug_active, &debug_push, &run_handler); | |
871 | 895 |
872 Bind(&debug_push); | 896 GotoUnless(is_debug_active, &promisehook_before); |
| 897 CallRuntime(Runtime::kDebugPushPromise, context, deferred_promise); |
| 898 Goto(&promisehook_before); |
| 899 |
| 900 Bind(&promisehook_before); |
873 { | 901 { |
874 CallRuntime(Runtime::kDebugPushPromise, context, deferred_promise); | 902 GotoUnless(IsPromiseHookEnabled(), &run_handler); |
| 903 CallRuntime(Runtime::kPromiseHookBefore, context, promise); |
875 Goto(&run_handler); | 904 Goto(&run_handler); |
876 } | 905 } |
877 | 906 |
878 Bind(&run_handler); | 907 Bind(&run_handler); |
879 { | 908 { |
880 Callable call_callable = CodeFactory::Call(isolate); | 909 Callable call_callable = CodeFactory::Call(isolate); |
881 | 910 |
882 Node* const result = | 911 Node* const result = |
883 CallJS(call_callable, context, handler, UndefinedConstant(), value); | 912 CallJS(call_callable, context, handler, UndefinedConstant(), value); |
884 | 913 |
885 GotoIfException(result, &if_rejectpromise, &var_reason); | 914 GotoIfException(result, &if_rejectpromise, &var_reason); |
886 | 915 |
887 // TODO(gsathya): Remove this lookup by getting rid of the deferred object. | 916 // TODO(gsathya): Remove this lookup by getting rid of the deferred object. |
888 Node* const key = HeapConstant(isolate->factory()->resolve_string()); | 917 Node* const key = HeapConstant(isolate->factory()->resolve_string()); |
889 Node* const on_resolve = | 918 Node* const on_resolve = |
890 CallStub(getproperty_callable, context, deferred, key); | 919 CallStub(getproperty_callable, context, deferred, key); |
891 | 920 |
892 Label if_internalhandler(this), if_customhandler(this, Label::kDeferred); | 921 Label if_internalhandler(this), if_customhandler(this, Label::kDeferred); |
893 Branch(IsUndefined(on_resolve), &if_internalhandler, &if_customhandler); | 922 Branch(IsUndefined(on_resolve), &if_internalhandler, &if_customhandler); |
894 | 923 |
895 Bind(&if_internalhandler); | 924 Bind(&if_internalhandler); |
896 InternalResolvePromise(context, deferred_promise, result, &debug_pop); | 925 InternalResolvePromise(context, deferred_promise, result, |
| 926 &promisehook_after); |
897 | 927 |
898 Bind(&if_customhandler); | 928 Bind(&if_customhandler); |
899 { | 929 { |
900 Node* const maybe_exception = CallJS(call_callable, context, on_resolve, | 930 Node* const maybe_exception = CallJS(call_callable, context, on_resolve, |
901 UndefinedConstant(), result); | 931 UndefinedConstant(), result); |
902 GotoIfException(maybe_exception, &if_rejectpromise, &var_reason); | 932 GotoIfException(maybe_exception, &if_rejectpromise, &var_reason); |
903 Goto(&debug_pop); | 933 Goto(&promisehook_after); |
904 } | 934 } |
905 } | 935 } |
906 | 936 |
907 Bind(&if_rejectpromise); | 937 Bind(&if_rejectpromise); |
908 { | 938 { |
909 // TODO(gsathya): Remove this lookup by getting rid of the deferred object. | 939 // TODO(gsathya): Remove this lookup by getting rid of the deferred object. |
910 Node* const key = HeapConstant(isolate->factory()->reject_string()); | 940 Node* const key = HeapConstant(isolate->factory()->reject_string()); |
911 Node* const on_reject = | 941 Node* const on_reject = |
912 CallStub(getproperty_callable, context, deferred, key); | 942 CallStub(getproperty_callable, context, deferred, key); |
913 | 943 |
914 Callable promise_handle_reject = CodeFactory::PromiseHandleReject(isolate); | 944 Callable promise_handle_reject = CodeFactory::PromiseHandleReject(isolate); |
915 CallStub(promise_handle_reject, context, deferred_promise, on_reject, | 945 CallStub(promise_handle_reject, context, deferred_promise, on_reject, |
916 var_reason.value()); | 946 var_reason.value()); |
| 947 Goto(&promisehook_after); |
| 948 } |
| 949 |
| 950 Bind(&promisehook_after); |
| 951 { |
| 952 GotoUnless(IsPromiseHookEnabled(), &debug_pop); |
| 953 CallRuntime(Runtime::kPromiseHookAfter, context, promise); |
917 Goto(&debug_pop); | 954 Goto(&debug_pop); |
918 } | 955 } |
919 | 956 |
920 Bind(&debug_pop); | 957 Bind(&debug_pop); |
921 { | 958 { |
922 Label out(this); | 959 Label out(this); |
923 | 960 |
924 GotoUnless(is_debug_active, &out); | 961 GotoUnless(is_debug_active, &out); |
925 CallRuntime(Runtime::kDebugPopPromise, context); | 962 CallRuntime(Runtime::kDebugPopPromise, context); |
926 Goto(&out); | 963 Goto(&out); |
927 | 964 |
928 Bind(&out); | 965 Bind(&out); |
929 Return(UndefinedConstant()); | 966 Return(UndefinedConstant()); |
930 } | 967 } |
931 } | 968 } |
932 | 969 |
933 } // namespace internal | 970 } // namespace internal |
934 } // namespace v8 | 971 } // namespace v8 |
OLD | NEW |