| 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-promise.h" | 5 #include "src/builtins/builtins-promise.h" |
| 6 #include "src/builtins/builtins-constructor.h" | 6 #include "src/builtins/builtins-constructor.h" |
| 7 #include "src/builtins/builtins-utils.h" | 7 #include "src/builtins/builtins-utils.h" |
| 8 #include "src/builtins/builtins.h" | 8 #include "src/builtins/builtins.h" |
| 9 #include "src/code-factory.h" | 9 #include "src/code-factory.h" |
| 10 #include "src/code-stub-assembler.h" | 10 #include "src/code-stub-assembler.h" |
| 11 #include "src/promise-utils.h" | 11 #include "src/promise-utils.h" |
| 12 | 12 |
| 13 namespace v8 { | 13 namespace v8 { |
| 14 namespace internal { | 14 namespace internal { |
| 15 | 15 |
| 16 typedef compiler::Node Node; | 16 typedef compiler::Node Node; |
| 17 typedef CodeStubAssembler::ParameterMode ParameterMode; | 17 typedef CodeStubAssembler::ParameterMode ParameterMode; |
| 18 typedef compiler::CodeAssemblerState CodeAssemblerState; | 18 typedef compiler::CodeAssemblerState CodeAssemblerState; |
| 19 | 19 |
| 20 Node* PromiseBuiltinsAssembler::AllocateAndInitPromise(Node* context, | 20 Node* PromiseBuiltinsAssembler::AllocateJSPromise(Node* context) { |
| 21 Node* parent) { | 21 Node* const native_context = LoadNativeContext(context); |
| 22 Node* const promise_fun = |
| 23 LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX); |
| 24 Node* const initial_map = |
| 25 LoadObjectField(promise_fun, JSFunction::kPrototypeOrInitialMapOffset); |
| 26 Node* const instance = AllocateJSObjectFromMap(initial_map); |
| 27 return instance; |
| 28 } |
| 29 |
| 30 void PromiseBuiltinsAssembler::PromiseInit(Node* promise) { |
| 31 StoreObjectField(promise, JSPromise::kStatusOffset, |
| 32 SmiConstant(v8::Promise::kPending)); |
| 33 StoreObjectField(promise, JSPromise::kFlagsOffset, SmiConstant(0)); |
| 34 } |
| 35 |
| 36 Node* PromiseBuiltinsAssembler::AllocateAndInitJSPromise(Node* context) { |
| 37 return AllocateAndInitJSPromise(context, UndefinedConstant()); |
| 38 } |
| 39 |
| 40 Node* PromiseBuiltinsAssembler::AllocateAndInitJSPromise(Node* context, |
| 41 Node* parent) { |
| 22 Node* const instance = AllocateJSPromise(context); | 42 Node* const instance = AllocateJSPromise(context); |
| 23 PromiseInit(instance); | 43 PromiseInit(instance); |
| 24 | 44 |
| 25 Label out(this); | 45 Label out(this); |
| 26 GotoUnless(IsPromiseHookEnabled(), &out); | 46 GotoUnless(IsPromiseHookEnabled(), &out); |
| 27 CallRuntime(Runtime::kPromiseHookInit, context, instance, parent); | 47 CallRuntime(Runtime::kPromiseHookInit, context, instance, parent); |
| 28 Goto(&out); | 48 Goto(&out); |
| 29 | 49 |
| 30 Bind(&out); | 50 Bind(&out); |
| 31 return instance; | 51 return instance; |
| 32 } | 52 } |
| 33 | 53 |
| 54 Node* PromiseBuiltinsAssembler::AllocateAndSetJSPromise(Node* context, |
| 55 Node* status, |
| 56 Node* result) { |
| 57 CSA_ASSERT(this, TaggedIsSmi(status)); |
| 58 |
| 59 Node* const instance = AllocateJSPromise(context); |
| 60 |
| 61 StoreObjectFieldNoWriteBarrier(instance, JSPromise::kStatusOffset, status); |
| 62 StoreObjectFieldNoWriteBarrier(instance, JSPromise::kResultOffset, result); |
| 63 StoreObjectFieldNoWriteBarrier(instance, JSPromise::kFlagsOffset, |
| 64 SmiConstant(0)); |
| 65 |
| 66 Label out(this); |
| 67 GotoUnless(IsPromiseHookEnabled(), &out); |
| 68 CallRuntime(Runtime::kPromiseHookInit, context, instance, |
| 69 UndefinedConstant()); |
| 70 Goto(&out); |
| 71 |
| 72 Bind(&out); |
| 73 return instance; |
| 74 } |
| 75 |
| 34 std::pair<Node*, Node*> | 76 std::pair<Node*, Node*> |
| 35 PromiseBuiltinsAssembler::CreatePromiseResolvingFunctions( | 77 PromiseBuiltinsAssembler::CreatePromiseResolvingFunctions( |
| 36 Node* promise, Node* debug_event, Node* native_context) { | 78 Node* promise, Node* debug_event, Node* native_context) { |
| 37 Node* const promise_context = CreatePromiseResolvingFunctionsContext( | 79 Node* const promise_context = CreatePromiseResolvingFunctionsContext( |
| 38 promise, debug_event, native_context); | 80 promise, debug_event, native_context); |
| 39 Node* const map = LoadContextElement( | 81 Node* const map = LoadContextElement( |
| 40 native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX); | 82 native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX); |
| 41 Node* const resolve_info = | 83 Node* const resolve_info = |
| 42 LoadContextElement(native_context, Context::PROMISE_RESOLVE_SHARED_FUN); | 84 LoadContextElement(native_context, Context::PROMISE_RESOLVE_SHARED_FUN); |
| 43 Node* const resolve = | 85 Node* const resolve = |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 330 perform_promise_then(this); | 372 perform_promise_then(this); |
| 331 Variable var_deferred_promise(this, MachineRepresentation::kTagged), | 373 Variable var_deferred_promise(this, MachineRepresentation::kTagged), |
| 332 var_deferred_on_resolve(this, MachineRepresentation::kTagged), | 374 var_deferred_on_resolve(this, MachineRepresentation::kTagged), |
| 333 var_deferred_on_reject(this, MachineRepresentation::kTagged); | 375 var_deferred_on_reject(this, MachineRepresentation::kTagged); |
| 334 | 376 |
| 335 Branch(WordEqual(promise_fun, constructor), &fast_promise_capability, | 377 Branch(WordEqual(promise_fun, constructor), &fast_promise_capability, |
| 336 &promise_capability); | 378 &promise_capability); |
| 337 | 379 |
| 338 Bind(&fast_promise_capability); | 380 Bind(&fast_promise_capability); |
| 339 { | 381 { |
| 340 Node* const deferred_promise = AllocateAndInitPromise(context, promise); | 382 Node* const deferred_promise = AllocateAndInitJSPromise(context, promise); |
| 341 var_deferred_promise.Bind(deferred_promise); | 383 var_deferred_promise.Bind(deferred_promise); |
| 342 var_deferred_on_resolve.Bind(UndefinedConstant()); | 384 var_deferred_on_resolve.Bind(UndefinedConstant()); |
| 343 var_deferred_on_reject.Bind(UndefinedConstant()); | 385 var_deferred_on_reject.Bind(UndefinedConstant()); |
| 344 Goto(&perform_promise_then); | 386 Goto(&perform_promise_then); |
| 345 } | 387 } |
| 346 | 388 |
| 347 Bind(&promise_capability); | 389 Bind(&promise_capability); |
| 348 { | 390 { |
| 349 Node* const capability = NewPromiseCapability(context, constructor); | 391 Node* const capability = NewPromiseCapability(context, constructor); |
| 350 var_deferred_promise.Bind( | 392 var_deferred_promise.Bind( |
| (...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 784 | 826 |
| 785 Node* const executor_map = LoadMap(executor); | 827 Node* const executor_map = LoadMap(executor); |
| 786 GotoUnless(IsCallableMap(executor_map), &if_notcallable); | 828 GotoUnless(IsCallableMap(executor_map), &if_notcallable); |
| 787 | 829 |
| 788 Node* const native_context = LoadNativeContext(context); | 830 Node* const native_context = LoadNativeContext(context); |
| 789 Node* const promise_fun = | 831 Node* const promise_fun = |
| 790 LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX); | 832 LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX); |
| 791 Node* const is_debug_active = IsDebugActive(); | 833 Node* const is_debug_active = IsDebugActive(); |
| 792 Label if_targetisnotmodified(this), | 834 Label if_targetisnotmodified(this), |
| 793 if_targetismodified(this, Label::kDeferred), run_executor(this), | 835 if_targetismodified(this, Label::kDeferred), run_executor(this), |
| 794 debug_push(this), init(this); | 836 debug_push(this); |
| 795 | 837 |
| 796 Branch(WordEqual(promise_fun, new_target), &if_targetisnotmodified, | 838 Branch(WordEqual(promise_fun, new_target), &if_targetisnotmodified, |
| 797 &if_targetismodified); | 839 &if_targetismodified); |
| 798 | 840 |
| 799 Variable var_result(this, MachineRepresentation::kTagged), | 841 Variable var_result(this, MachineRepresentation::kTagged), |
| 800 var_reject_call(this, MachineRepresentation::kTagged), | 842 var_reject_call(this, MachineRepresentation::kTagged), |
| 801 var_reason(this, MachineRepresentation::kTagged); | 843 var_reason(this, MachineRepresentation::kTagged); |
| 802 | 844 |
| 803 Bind(&if_targetisnotmodified); | 845 Bind(&if_targetisnotmodified); |
| 804 { | 846 { |
| 805 Node* const instance = AllocateJSPromise(context); | 847 Node* const instance = AllocateAndInitJSPromise(context); |
| 806 var_result.Bind(instance); | 848 var_result.Bind(instance); |
| 807 Goto(&init); | 849 Goto(&debug_push); |
| 808 } | 850 } |
| 809 | 851 |
| 810 Bind(&if_targetismodified); | 852 Bind(&if_targetismodified); |
| 811 { | 853 { |
| 812 ConstructorBuiltinsAssembler constructor_assembler(this->state()); | 854 ConstructorBuiltinsAssembler constructor_assembler(this->state()); |
| 813 Node* const instance = constructor_assembler.EmitFastNewObject( | 855 Node* const instance = constructor_assembler.EmitFastNewObject( |
| 814 context, promise_fun, new_target); | 856 context, promise_fun, new_target); |
| 857 PromiseInit(instance); |
| 858 var_result.Bind(instance); |
| 815 | 859 |
| 816 var_result.Bind(instance); | |
| 817 Goto(&init); | |
| 818 } | |
| 819 | |
| 820 Bind(&init); | |
| 821 { | |
| 822 PromiseInit(var_result.value()); | |
| 823 GotoUnless(IsPromiseHookEnabled(), &debug_push); | 860 GotoUnless(IsPromiseHookEnabled(), &debug_push); |
| 824 CallRuntime(Runtime::kPromiseHookInit, context, var_result.value(), | 861 CallRuntime(Runtime::kPromiseHookInit, context, instance, |
| 825 UndefinedConstant()); | 862 UndefinedConstant()); |
| 826 Goto(&debug_push); | 863 Goto(&debug_push); |
| 827 } | 864 } |
| 828 | 865 |
| 829 Bind(&debug_push); | 866 Bind(&debug_push); |
| 830 { | 867 { |
| 831 GotoUnless(is_debug_active, &run_executor); | 868 GotoUnless(is_debug_active, &run_executor); |
| 832 CallRuntime(Runtime::kDebugPushPromise, context, var_result.value()); | 869 CallRuntime(Runtime::kDebugPushPromise, context, var_result.value()); |
| 833 Goto(&run_executor); | 870 Goto(&run_executor); |
| 834 } | 871 } |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 879 Node* const message_id = | 916 Node* const message_id = |
| 880 SmiConstant(MessageTemplate::kResolverNotAFunction); | 917 SmiConstant(MessageTemplate::kResolverNotAFunction); |
| 881 CallRuntime(Runtime::kThrowTypeError, context, message_id, executor); | 918 CallRuntime(Runtime::kThrowTypeError, context, message_id, executor); |
| 882 Return(UndefinedConstant()); // Never reached. | 919 Return(UndefinedConstant()); // Never reached. |
| 883 } | 920 } |
| 884 } | 921 } |
| 885 | 922 |
| 886 TF_BUILTIN(PromiseInternalConstructor, PromiseBuiltinsAssembler) { | 923 TF_BUILTIN(PromiseInternalConstructor, PromiseBuiltinsAssembler) { |
| 887 Node* const parent = Parameter(1); | 924 Node* const parent = Parameter(1); |
| 888 Node* const context = Parameter(4); | 925 Node* const context = Parameter(4); |
| 889 Return(AllocateAndInitPromise(context, parent)); | 926 Return(AllocateAndInitJSPromise(context, parent)); |
| 890 } | 927 } |
| 891 | 928 |
| 892 TF_BUILTIN(PromiseCreateAndSet, PromiseBuiltinsAssembler) { | 929 TF_BUILTIN(PromiseCreateAndSet, PromiseBuiltinsAssembler) { |
| 893 Node* const status = Parameter(1); | 930 Node* const status = Parameter(1); |
| 894 Node* const result = Parameter(2); | 931 Node* const result = Parameter(2); |
| 895 Node* const context = Parameter(5); | 932 Node* const context = Parameter(5); |
| 896 | 933 |
| 897 Node* const instance = AllocateJSPromise(context); | 934 Node* const instance = AllocateAndSetJSPromise(context, status, result); |
| 898 PromiseSet(instance, status, result); | |
| 899 | |
| 900 Label out(this); | |
| 901 GotoUnless(IsPromiseHookEnabled(), &out); | |
| 902 CallRuntime(Runtime::kPromiseHookInit, context, instance, | |
| 903 UndefinedConstant()); | |
| 904 Goto(&out); | |
| 905 Bind(&out); | |
| 906 Return(instance); | 935 Return(instance); |
| 907 } | 936 } |
| 908 | 937 |
| 909 TF_BUILTIN(IsPromise, PromiseBuiltinsAssembler) { | 938 TF_BUILTIN(IsPromise, PromiseBuiltinsAssembler) { |
| 910 Node* const maybe_promise = Parameter(1); | 939 Node* const maybe_promise = Parameter(1); |
| 911 Label if_notpromise(this, Label::kDeferred); | 940 Label if_notpromise(this, Label::kDeferred); |
| 912 | 941 |
| 913 GotoIf(TaggedIsSmi(maybe_promise), &if_notpromise); | 942 GotoIf(TaggedIsSmi(maybe_promise), &if_notpromise); |
| 914 | 943 |
| 915 Node* const result = | 944 Node* const result = |
| (...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1168 Node* debug_event = Parameter(2); | 1197 Node* debug_event = Parameter(2); |
| 1169 Node* context = Parameter(5); | 1198 Node* context = Parameter(5); |
| 1170 | 1199 |
| 1171 CSA_ASSERT_JS_ARGC_EQ(this, 2); | 1200 CSA_ASSERT_JS_ARGC_EQ(this, 2); |
| 1172 | 1201 |
| 1173 Return(NewPromiseCapability(context, constructor, debug_event)); | 1202 Return(NewPromiseCapability(context, constructor, debug_event)); |
| 1174 } | 1203 } |
| 1175 | 1204 |
| 1176 } // namespace internal | 1205 } // namespace internal |
| 1177 } // namespace v8 | 1206 } // namespace v8 |
| OLD | NEW |