Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(544)

Side by Side Diff: src/builtins/builtins-promise.cc

Issue 2575313002: [promisehook] Implement PromiseHook (Closed)
Patch Set: add tests Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/builtins/builtins.h ('k') | src/code-stub-assembler.cc » ('j') | src/isolate.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698