| 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 |
| 11 namespace v8 { | 11 namespace v8 { |
| 12 namespace internal { | 12 namespace internal { |
| 13 | 13 |
| 14 // ES#sec-promise-reject-functions | 14 // ES#sec-promise-reject-functions |
| 15 // Promise Reject Functions | 15 // Promise Reject Functions |
| 16 BUILTIN(PromiseRejectClosure) { | 16 BUILTIN(PromiseRejectClosure) { |
| 17 HandleScope scope(isolate); | 17 HandleScope scope(isolate); |
| 18 | 18 |
| 19 Handle<Context> context(isolate->context(), isolate); | 19 Handle<Context> context(isolate->context(), isolate); |
| 20 | 20 |
| 21 if (PromiseUtils::HasAlreadyVisited(context)) { | 21 if (PromiseUtils::HasAlreadyVisited(context)) { |
| 22 return isolate->heap()->undefined_value(); | 22 return isolate->heap()->undefined_value(); |
| 23 } | 23 } |
| 24 | 24 |
| 25 PromiseUtils::SetAlreadyVisited(context); | 25 PromiseUtils::SetAlreadyVisited(context); |
| 26 Handle<Object> value = args.atOrUndefined(isolate, 1); | 26 Handle<Object> value = args.atOrUndefined(isolate, 1); |
| 27 Handle<JSObject> promise = handle(PromiseUtils::GetPromise(context), isolate); | 27 Handle<JSPromise> promise = |
| 28 handle(PromiseUtils::GetPromise(context), isolate); |
| 28 Handle<Object> debug_event = | 29 Handle<Object> debug_event = |
| 29 handle(PromiseUtils::GetDebugEvent(context), isolate); | 30 handle(PromiseUtils::GetDebugEvent(context), isolate); |
| 30 MaybeHandle<Object> maybe_result; | 31 MaybeHandle<Object> maybe_result; |
| 31 Handle<Object> argv[] = {promise, value, debug_event}; | 32 Handle<Object> argv[] = {promise, value, debug_event}; |
| 33 |
| 34 isolate->RunPromiseHook(PromiseHookType::kResolve, promise, |
| 35 isolate->factory()->undefined_value()); |
| 36 |
| 32 RETURN_FAILURE_ON_EXCEPTION( | 37 RETURN_FAILURE_ON_EXCEPTION( |
| 33 isolate, Execution::Call(isolate, isolate->promise_internal_reject(), | 38 isolate, Execution::Call(isolate, isolate->promise_internal_reject(), |
| 34 isolate->factory()->undefined_value(), | 39 isolate->factory()->undefined_value(), |
| 35 arraysize(argv), argv)); | 40 arraysize(argv), argv)); |
| 36 return isolate->heap()->undefined_value(); | 41 return isolate->heap()->undefined_value(); |
| 37 } | 42 } |
| 38 | 43 |
| 39 // ES#sec-createresolvingfunctions | 44 // ES#sec-createresolvingfunctions |
| 40 // CreateResolvingFunctions ( promise ) | 45 // CreateResolvingFunctions ( promise ) |
| 41 BUILTIN(CreateResolvingFunctions) { | 46 BUILTIN(CreateResolvingFunctions) { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 91 &if_targetismodified); | 96 &if_targetismodified); |
| 92 | 97 |
| 93 Variable var_result(&a, MachineRepresentation::kTagged), | 98 Variable var_result(&a, MachineRepresentation::kTagged), |
| 94 var_reject_call(&a, MachineRepresentation::kTagged), | 99 var_reject_call(&a, MachineRepresentation::kTagged), |
| 95 var_reason(&a, MachineRepresentation::kTagged); | 100 var_reason(&a, MachineRepresentation::kTagged); |
| 96 | 101 |
| 97 a.Bind(&if_targetisnotmodified); | 102 a.Bind(&if_targetisnotmodified); |
| 98 { | 103 { |
| 99 Node* const instance = a.AllocateJSPromise(context); | 104 Node* const instance = a.AllocateJSPromise(context); |
| 100 var_result.Bind(instance); | 105 var_result.Bind(instance); |
| 106 a.GotoUnless(a.IsPromiseHookEnabled(), &init); |
| 107 a.CallRuntime(Runtime::kPromiseHookInit, context, instance, |
| 108 a.UndefinedConstant()); |
| 101 a.Goto(&init); | 109 a.Goto(&init); |
| 102 } | 110 } |
| 103 | 111 |
| 104 a.Bind(&if_targetismodified); | 112 a.Bind(&if_targetismodified); |
| 105 { | 113 { |
| 106 Callable fast_new_object_stub = CodeFactory::FastNewObject(isolate); | 114 Callable fast_new_object_stub = CodeFactory::FastNewObject(isolate); |
| 107 Node* const instance = | 115 Node* const instance = |
| 108 a.CallStub(fast_new_object_stub, context, promise_fun, new_target); | 116 a.CallStub(fast_new_object_stub, context, promise_fun, new_target); |
| 109 | 117 |
| 110 var_result.Bind(instance); | 118 var_result.Bind(instance); |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 174 Node* const message_id = | 182 Node* const message_id = |
| 175 a.SmiConstant(MessageTemplate::kResolverNotAFunction); | 183 a.SmiConstant(MessageTemplate::kResolverNotAFunction); |
| 176 a.CallRuntime(Runtime::kThrowTypeError, context, message_id, executor); | 184 a.CallRuntime(Runtime::kThrowTypeError, context, message_id, executor); |
| 177 a.Return(a.UndefinedConstant()); // Never reached. | 185 a.Return(a.UndefinedConstant()); // Never reached. |
| 178 } | 186 } |
| 179 } | 187 } |
| 180 | 188 |
| 181 void Builtins::Generate_PromiseInternalConstructor( | 189 void Builtins::Generate_PromiseInternalConstructor( |
| 182 compiler::CodeAssemblerState* state) { | 190 compiler::CodeAssemblerState* state) { |
| 183 typedef compiler::Node Node; | 191 typedef compiler::Node Node; |
| 192 typedef CodeStubAssembler::Label Label; |
| 184 CodeStubAssembler a(state); | 193 CodeStubAssembler a(state); |
| 185 | 194 |
| 186 Node* const context = a.Parameter(3); | 195 Node* const parent = a.Parameter(1); |
| 196 Node* const context = a.Parameter(4); |
| 187 Node* const instance = a.AllocateJSPromise(context); | 197 Node* const instance = a.AllocateJSPromise(context); |
| 188 a.PromiseInit(instance); | 198 a.PromiseInit(instance); |
| 199 |
| 200 Label out(&a); |
| 201 a.GotoUnless(a.IsPromiseHookEnabled(), &out); |
| 202 a.CallRuntime(Runtime::kPromiseHookInit, context, instance, parent); |
| 203 a.Goto(&out); |
| 204 a.Bind(&out); |
| 189 a.Return(instance); | 205 a.Return(instance); |
| 190 } | 206 } |
| 191 | 207 |
| 192 void Builtins::Generate_PromiseCreateAndSet( | 208 void Builtins::Generate_PromiseCreateAndSet( |
| 193 compiler::CodeAssemblerState* state) { | 209 compiler::CodeAssemblerState* state) { |
| 194 typedef compiler::Node Node; | 210 typedef compiler::Node Node; |
| 211 typedef CodeStubAssembler::Label Label; |
| 195 CodeStubAssembler a(state); | 212 CodeStubAssembler a(state); |
| 196 | 213 |
| 197 Node* const status = a.Parameter(1); | 214 Node* const status = a.Parameter(1); |
| 198 Node* const result = a.Parameter(2); | 215 Node* const result = a.Parameter(2); |
| 199 Node* const context = a.Parameter(5); | 216 Node* const context = a.Parameter(5); |
| 200 | 217 |
| 201 Node* const instance = a.AllocateJSPromise(context); | 218 Node* const instance = a.AllocateJSPromise(context); |
| 202 a.PromiseSet(instance, status, result); | 219 a.PromiseSet(instance, status, result); |
| 220 |
| 221 Label out(&a); |
| 222 a.GotoUnless(a.IsPromiseHookEnabled(), &out); |
| 223 a.CallRuntime(Runtime::kPromiseHookInit, context, instance, |
| 224 a.UndefinedConstant()); |
| 225 a.Goto(&out); |
| 226 a.Bind(&out); |
| 203 a.Return(instance); | 227 a.Return(instance); |
| 204 } | 228 } |
| 205 | 229 |
| 206 namespace { | 230 namespace { |
| 207 | 231 |
| 208 compiler::Node* ThrowIfNotJSReceiver(CodeStubAssembler* a, Isolate* isolate, | 232 compiler::Node* ThrowIfNotJSReceiver(CodeStubAssembler* a, Isolate* isolate, |
| 209 compiler::Node* context, | 233 compiler::Node* context, |
| 210 compiler::Node* value, | 234 compiler::Node* value, |
| 211 MessageTemplate::Template msg_template) { | 235 MessageTemplate::Template msg_template) { |
| 212 typedef compiler::Node Node; | 236 typedef compiler::Node Node; |
| (...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 597 | 621 |
| 598 // TODO(gsathya): Remove deferred object and move | 622 // TODO(gsathya): Remove deferred object and move |
| 599 // NewPromiseCapbability functions to TF. | 623 // NewPromiseCapbability functions to TF. |
| 600 a.Bind(&fast_promise_capability); | 624 a.Bind(&fast_promise_capability); |
| 601 { | 625 { |
| 602 // TODO(gsathya): Move this to TF. | 626 // TODO(gsathya): Move this to TF. |
| 603 Node* const promise_internal_capability = a.LoadContextElement( | 627 Node* const promise_internal_capability = a.LoadContextElement( |
| 604 native_context, Context::INTERNAL_PROMISE_CAPABILITY_INDEX); | 628 native_context, Context::INTERNAL_PROMISE_CAPABILITY_INDEX); |
| 605 Node* const capability = | 629 Node* const capability = |
| 606 a.CallJS(call_callable, context, promise_internal_capability, | 630 a.CallJS(call_callable, context, promise_internal_capability, |
| 607 a.UndefinedConstant()); | 631 a.UndefinedConstant(), promise); |
| 608 var_deferred.Bind(capability); | 632 var_deferred.Bind(capability); |
| 609 a.Goto(&perform_promise_then); | 633 a.Goto(&perform_promise_then); |
| 610 } | 634 } |
| 611 | 635 |
| 612 a.Bind(&promise_capability); | 636 a.Bind(&promise_capability); |
| 613 { | 637 { |
| 614 // TODO(gsathya): Move this to TF. | 638 // TODO(gsathya): Move this to TF. |
| 615 Node* const new_promise_capability = a.LoadContextElement( | 639 Node* const new_promise_capability = a.LoadContextElement( |
| 616 native_context, Context::NEW_PROMISE_CAPABILITY_INDEX); | 640 native_context, Context::NEW_PROMISE_CAPABILITY_INDEX); |
| 617 Node* const capability = | 641 Node* const capability = |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 839 // 4. If alreadyResolved.[[Value]] is true, return undefined. | 863 // 4. If alreadyResolved.[[Value]] is true, return undefined. |
| 840 a.GotoIf(a.SmiEqual(has_already_visited, a.SmiConstant(1)), &out); | 864 a.GotoIf(a.SmiEqual(has_already_visited, a.SmiConstant(1)), &out); |
| 841 | 865 |
| 842 // 5.Set alreadyResolved.[[Value]] to true. | 866 // 5.Set alreadyResolved.[[Value]] to true. |
| 843 a.StoreFixedArrayElement(context, has_already_visited_slot, a.SmiConstant(1)); | 867 a.StoreFixedArrayElement(context, has_already_visited_slot, a.SmiConstant(1)); |
| 844 | 868 |
| 845 // 2. Let promise be F.[[Promise]]. | 869 // 2. Let promise be F.[[Promise]]. |
| 846 Node* const promise = a.LoadFixedArrayElement( | 870 Node* const promise = a.LoadFixedArrayElement( |
| 847 context, a.IntPtrConstant(PromiseUtils::kPromiseSlot)); | 871 context, a.IntPtrConstant(PromiseUtils::kPromiseSlot)); |
| 848 | 872 |
| 873 Label run_resolve(&a); |
| 874 a.GotoUnless(a.IsPromiseHookEnabled(), &run_resolve); |
| 875 a.CallRuntime(Runtime::kPromiseHookResolve, context, promise); |
| 876 a.Goto(&run_resolve); |
| 877 |
| 878 a.Bind(&run_resolve); |
| 849 InternalResolvePromise(&a, context, promise, value, &out); | 879 InternalResolvePromise(&a, context, promise, value, &out); |
| 850 | 880 |
| 851 a.Bind(&out); | 881 a.Bind(&out); |
| 852 a.Return(a.UndefinedConstant()); | 882 a.Return(a.UndefinedConstant()); |
| 853 } | 883 } |
| 854 | 884 |
| 855 void Builtins::Generate_ResolvePromise(compiler::CodeAssemblerState* state) { | 885 void Builtins::Generate_ResolvePromise(compiler::CodeAssemblerState* state) { |
| 856 CodeStubAssembler a(state); | 886 CodeStubAssembler a(state); |
| 857 typedef compiler::Node Node; | 887 typedef compiler::Node Node; |
| 858 typedef CodeStubAssembler::Label Label; | 888 typedef CodeStubAssembler::Label Label; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 902 a.Return(a.UndefinedConstant()); | 932 a.Return(a.UndefinedConstant()); |
| 903 } | 933 } |
| 904 } | 934 } |
| 905 | 935 |
| 906 void Builtins::Generate_PromiseHandle(compiler::CodeAssemblerState* state) { | 936 void Builtins::Generate_PromiseHandle(compiler::CodeAssemblerState* state) { |
| 907 CodeStubAssembler a(state); | 937 CodeStubAssembler a(state); |
| 908 typedef compiler::Node Node; | 938 typedef compiler::Node Node; |
| 909 typedef CodeStubAssembler::Label Label; | 939 typedef CodeStubAssembler::Label Label; |
| 910 typedef CodeStubAssembler::Variable Variable; | 940 typedef CodeStubAssembler::Variable Variable; |
| 911 | 941 |
| 942 Node* const promise = a.Parameter(1); |
| 912 Node* const value = a.Parameter(2); | 943 Node* const value = a.Parameter(2); |
| 913 Node* const handler = a.Parameter(3); | 944 Node* const handler = a.Parameter(3); |
| 914 Node* const deferred = a.Parameter(4); | 945 Node* const deferred = a.Parameter(4); |
| 915 Node* const context = a.Parameter(7); | 946 Node* const context = a.Parameter(7); |
| 916 Isolate* isolate = a.isolate(); | 947 Isolate* isolate = a.isolate(); |
| 917 | 948 |
| 918 // Get promise from deferred | 949 // Get promise from deferred |
| 919 // 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. |
| 920 Callable getproperty_callable = CodeFactory::GetProperty(isolate); | 951 Callable getproperty_callable = CodeFactory::GetProperty(isolate); |
| 921 Node* const key = a.HeapConstant(isolate->factory()->promise_string()); | 952 Node* const key = a.HeapConstant(isolate->factory()->promise_string()); |
| 922 Node* const deferred_promise = | 953 Node* const deferred_promise = |
| 923 a.CallStub(getproperty_callable, context, deferred, key); | 954 a.CallStub(getproperty_callable, context, deferred, key); |
| 924 | 955 |
| 925 Variable var_reason(&a, MachineRepresentation::kTagged); | 956 Variable var_reason(&a, MachineRepresentation::kTagged); |
| 926 | 957 |
| 927 Node* const is_debug_active = a.IsDebugActive(); | 958 Node* const is_debug_active = a.IsDebugActive(); |
| 928 Label run_handler(&a), if_rejectpromise(&a), debug_push(&a, Label::kDeferred), | 959 Label run_handler(&a), if_rejectpromise(&a), debug_push(&a, Label::kDeferred), |
| 929 debug_pop(&a, Label::kDeferred); | 960 debug_pop(&a), promisehook_after(&a); |
| 930 a.Branch(is_debug_active, &debug_push, &run_handler); | 961 |
| 962 a.GotoUnless(a.IsPromiseHookEnabled(), &debug_push); |
| 963 a.CallRuntime(Runtime::kPromiseHookBefore, context, promise); |
| 964 a.Goto(&debug_push); |
| 931 | 965 |
| 932 a.Bind(&debug_push); | 966 a.Bind(&debug_push); |
| 933 { | 967 { |
| 968 a.GotoUnless(is_debug_active, &run_handler); |
| 934 a.CallRuntime(Runtime::kDebugPushPromise, context, deferred_promise); | 969 a.CallRuntime(Runtime::kDebugPushPromise, context, deferred_promise); |
| 935 a.Goto(&run_handler); | 970 a.Goto(&run_handler); |
| 936 } | 971 } |
| 937 | 972 |
| 938 a.Bind(&run_handler); | 973 a.Bind(&run_handler); |
| 939 { | 974 { |
| 940 Callable call_callable = CodeFactory::Call(isolate); | 975 Callable call_callable = CodeFactory::Call(isolate); |
| 941 | 976 |
| 942 Node* const result = | 977 Node* const result = |
| 943 a.CallJS(call_callable, context, handler, a.UndefinedConstant(), value); | 978 a.CallJS(call_callable, context, handler, a.UndefinedConstant(), value); |
| 944 | 979 |
| 945 a.GotoIfException(result, &if_rejectpromise, &var_reason); | 980 a.GotoIfException(result, &if_rejectpromise, &var_reason); |
| 946 | 981 |
| 947 // TODO(gsathya): Remove this lookup by getting rid of the deferred object. | 982 // TODO(gsathya): Remove this lookup by getting rid of the deferred object. |
| 948 Node* const key = a.HeapConstant(isolate->factory()->resolve_string()); | 983 Node* const key = a.HeapConstant(isolate->factory()->resolve_string()); |
| 949 Node* const on_resolve = | 984 Node* const on_resolve = |
| 950 a.CallStub(getproperty_callable, context, deferred, key); | 985 a.CallStub(getproperty_callable, context, deferred, key); |
| 951 | 986 |
| 952 Label if_internalhandler(&a), if_customhandler(&a, Label::kDeferred); | 987 Label if_internalhandler(&a), if_customhandler(&a, Label::kDeferred); |
| 953 a.Branch(a.IsUndefined(on_resolve), &if_internalhandler, &if_customhandler); | 988 a.Branch(a.IsUndefined(on_resolve), &if_internalhandler, &if_customhandler); |
| 954 | 989 |
| 955 a.Bind(&if_internalhandler); | 990 a.Bind(&if_internalhandler); |
| 956 InternalResolvePromise(&a, context, deferred_promise, result, &debug_pop); | 991 InternalResolvePromise(&a, context, deferred_promise, result, |
| 992 &promisehook_after); |
| 957 | 993 |
| 958 a.Bind(&if_customhandler); | 994 a.Bind(&if_customhandler); |
| 959 { | 995 { |
| 960 Node* const maybe_exception = a.CallJS(call_callable, context, on_resolve, | 996 Node* const maybe_exception = a.CallJS(call_callable, context, on_resolve, |
| 961 a.UndefinedConstant(), result); | 997 a.UndefinedConstant(), result); |
| 962 a.GotoIfException(maybe_exception, &if_rejectpromise, &var_reason); | 998 a.GotoIfException(maybe_exception, &if_rejectpromise, &var_reason); |
| 963 a.Goto(&debug_pop); | 999 a.Goto(&promisehook_after); |
| 964 } | 1000 } |
| 965 } | 1001 } |
| 966 | 1002 |
| 967 a.Bind(&if_rejectpromise); | 1003 a.Bind(&if_rejectpromise); |
| 968 { | 1004 { |
| 969 // TODO(gsathya): Remove this lookup by getting rid of the deferred object. | 1005 // TODO(gsathya): Remove this lookup by getting rid of the deferred object. |
| 970 Node* const key = a.HeapConstant(isolate->factory()->reject_string()); | 1006 Node* const key = a.HeapConstant(isolate->factory()->reject_string()); |
| 971 Node* const on_reject = | 1007 Node* const on_reject = |
| 972 a.CallStub(getproperty_callable, context, deferred, key); | 1008 a.CallStub(getproperty_callable, context, deferred, key); |
| 973 | 1009 |
| 974 Callable promise_handle_reject = CodeFactory::PromiseHandleReject(isolate); | 1010 Callable promise_handle_reject = CodeFactory::PromiseHandleReject(isolate); |
| 975 a.CallStub(promise_handle_reject, context, deferred_promise, on_reject, | 1011 a.CallStub(promise_handle_reject, context, deferred_promise, on_reject, |
| 976 var_reason.value()); | 1012 var_reason.value()); |
| 1013 a.Goto(&promisehook_after); |
| 1014 } |
| 1015 |
| 1016 a.Bind(&promisehook_after); |
| 1017 { |
| 1018 a.GotoUnless(a.IsPromiseHookEnabled(), &debug_pop); |
| 1019 a.CallRuntime(Runtime::kPromiseHookAfter, context, promise); |
| 977 a.Goto(&debug_pop); | 1020 a.Goto(&debug_pop); |
| 978 } | 1021 } |
| 979 | 1022 |
| 980 a.Bind(&debug_pop); | 1023 a.Bind(&debug_pop); |
| 981 { | 1024 { |
| 982 Label out(&a); | 1025 Label out(&a); |
| 983 | |
| 984 a.GotoUnless(is_debug_active, &out); | 1026 a.GotoUnless(is_debug_active, &out); |
| 985 a.CallRuntime(Runtime::kDebugPopPromise, context); | 1027 a.CallRuntime(Runtime::kDebugPopPromise, context); |
| 986 a.Goto(&out); | 1028 a.Goto(&out); |
| 987 | 1029 |
| 988 a.Bind(&out); | 1030 a.Bind(&out); |
| 989 a.Return(a.UndefinedConstant()); | 1031 a.Return(a.UndefinedConstant()); |
| 990 } | 1032 } |
| 991 } | 1033 } |
| 992 | 1034 |
| 993 } // namespace internal | 1035 } // namespace internal |
| 994 } // namespace v8 | 1036 } // namespace v8 |
| OLD | NEW |