| 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 |