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