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

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

Issue 2575313002: [promisehook] Implement PromiseHook (Closed)
Patch Set: move resolve hook 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<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
32 RETURN_FAILURE_ON_EXCEPTION( 34 RETURN_FAILURE_ON_EXCEPTION(
33 isolate, Execution::Call(isolate, isolate->promise_internal_reject(), 35 isolate, Execution::Call(isolate, isolate->promise_internal_reject(),
34 isolate->factory()->undefined_value(), 36 isolate->factory()->undefined_value(),
35 arraysize(argv), argv)); 37 arraysize(argv), argv));
36 return isolate->heap()->undefined_value(); 38 return isolate->heap()->undefined_value();
37 } 39 }
38 40
39 // ES#sec-createresolvingfunctions 41 // ES#sec-createresolvingfunctions
40 // CreateResolvingFunctions ( promise ) 42 // CreateResolvingFunctions ( promise )
41 BUILTIN(CreateResolvingFunctions) { 43 BUILTIN(CreateResolvingFunctions) {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
91 &if_targetismodified); 93 &if_targetismodified);
92 94
93 Variable var_result(&a, MachineRepresentation::kTagged), 95 Variable var_result(&a, MachineRepresentation::kTagged),
94 var_reject_call(&a, MachineRepresentation::kTagged), 96 var_reject_call(&a, MachineRepresentation::kTagged),
95 var_reason(&a, MachineRepresentation::kTagged); 97 var_reason(&a, MachineRepresentation::kTagged);
96 98
97 a.Bind(&if_targetisnotmodified); 99 a.Bind(&if_targetisnotmodified);
98 { 100 {
99 Node* const instance = a.AllocateJSPromise(context); 101 Node* const instance = a.AllocateJSPromise(context);
100 var_result.Bind(instance); 102 var_result.Bind(instance);
103 a.GotoUnless(a.IsPromiseHookEnabled(), &init);
104 a.CallRuntime(Runtime::kPromiseHookInit, context, instance,
105 a.UndefinedConstant());
101 a.Goto(&init); 106 a.Goto(&init);
102 } 107 }
103 108
104 a.Bind(&if_targetismodified); 109 a.Bind(&if_targetismodified);
105 { 110 {
106 Callable fast_new_object_stub = CodeFactory::FastNewObject(isolate); 111 Callable fast_new_object_stub = CodeFactory::FastNewObject(isolate);
107 Node* const instance = 112 Node* const instance =
108 a.CallStub(fast_new_object_stub, context, promise_fun, new_target); 113 a.CallStub(fast_new_object_stub, context, promise_fun, new_target);
109 114
110 var_result.Bind(instance); 115 var_result.Bind(instance);
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 Node* const message_id = 179 Node* const message_id =
175 a.SmiConstant(MessageTemplate::kResolverNotAFunction); 180 a.SmiConstant(MessageTemplate::kResolverNotAFunction);
176 a.CallRuntime(Runtime::kThrowTypeError, context, message_id, executor); 181 a.CallRuntime(Runtime::kThrowTypeError, context, message_id, executor);
177 a.Return(a.UndefinedConstant()); // Never reached. 182 a.Return(a.UndefinedConstant()); // Never reached.
178 } 183 }
179 } 184 }
180 185
181 void Builtins::Generate_PromiseInternalConstructor( 186 void Builtins::Generate_PromiseInternalConstructor(
182 compiler::CodeAssemblerState* state) { 187 compiler::CodeAssemblerState* state) {
183 typedef compiler::Node Node; 188 typedef compiler::Node Node;
189 typedef CodeStubAssembler::Label Label;
184 CodeStubAssembler a(state); 190 CodeStubAssembler a(state);
185 191
186 Node* const context = a.Parameter(3); 192 Node* const parent = a.Parameter(1);
193 Node* const context = a.Parameter(4);
187 Node* const instance = a.AllocateJSPromise(context); 194 Node* const instance = a.AllocateJSPromise(context);
188 a.PromiseInit(instance); 195 a.PromiseInit(instance);
196
197 Label out(&a);
198 a.GotoUnless(a.IsPromiseHookEnabled(), &out);
199 a.CallRuntime(Runtime::kPromiseHookInit, context, instance, parent);
200 a.Goto(&out);
201 a.Bind(&out);
189 a.Return(instance); 202 a.Return(instance);
190 } 203 }
191 204
192 void Builtins::Generate_PromiseCreateAndSet( 205 void Builtins::Generate_PromiseCreateAndSet(
193 compiler::CodeAssemblerState* state) { 206 compiler::CodeAssemblerState* state) {
194 typedef compiler::Node Node; 207 typedef compiler::Node Node;
208 typedef CodeStubAssembler::Label Label;
195 CodeStubAssembler a(state); 209 CodeStubAssembler a(state);
196 210
197 Node* const status = a.Parameter(1); 211 Node* const status = a.Parameter(1);
198 Node* const result = a.Parameter(2); 212 Node* const result = a.Parameter(2);
199 Node* const context = a.Parameter(5); 213 Node* const context = a.Parameter(5);
200 214
201 Node* const instance = a.AllocateJSPromise(context); 215 Node* const instance = a.AllocateJSPromise(context);
202 a.PromiseSet(instance, status, result); 216 a.PromiseSet(instance, status, result);
217
218 Label out(&a);
219 a.GotoUnless(a.IsPromiseHookEnabled(), &out);
220 a.CallRuntime(Runtime::kPromiseHookInit, context, instance,
221 a.UndefinedConstant());
222 a.Goto(&out);
223 a.Bind(&out);
203 a.Return(instance); 224 a.Return(instance);
204 } 225 }
205 226
206 namespace { 227 namespace {
207 228
208 compiler::Node* ThrowIfNotJSReceiver(CodeStubAssembler* a, Isolate* isolate, 229 compiler::Node* ThrowIfNotJSReceiver(CodeStubAssembler* a, Isolate* isolate,
209 compiler::Node* context, 230 compiler::Node* context,
210 compiler::Node* value, 231 compiler::Node* value,
211 MessageTemplate::Template msg_template) { 232 MessageTemplate::Template msg_template) {
212 typedef compiler::Node Node; 233 typedef compiler::Node Node;
(...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after
597 618
598 // TODO(gsathya): Remove deferred object and move 619 // TODO(gsathya): Remove deferred object and move
599 // NewPromiseCapbability functions to TF. 620 // NewPromiseCapbability functions to TF.
600 a.Bind(&fast_promise_capability); 621 a.Bind(&fast_promise_capability);
601 { 622 {
602 // TODO(gsathya): Move this to TF. 623 // TODO(gsathya): Move this to TF.
603 Node* const promise_internal_capability = a.LoadContextElement( 624 Node* const promise_internal_capability = a.LoadContextElement(
604 native_context, Context::INTERNAL_PROMISE_CAPABILITY_INDEX); 625 native_context, Context::INTERNAL_PROMISE_CAPABILITY_INDEX);
605 Node* const capability = 626 Node* const capability =
606 a.CallJS(call_callable, context, promise_internal_capability, 627 a.CallJS(call_callable, context, promise_internal_capability,
607 a.UndefinedConstant()); 628 a.UndefinedConstant(), promise);
608 var_deferred.Bind(capability); 629 var_deferred.Bind(capability);
609 a.Goto(&perform_promise_then); 630 a.Goto(&perform_promise_then);
610 } 631 }
611 632
612 a.Bind(&promise_capability); 633 a.Bind(&promise_capability);
613 { 634 {
614 // TODO(gsathya): Move this to TF. 635 // TODO(gsathya): Move this to TF.
615 Node* const new_promise_capability = a.LoadContextElement( 636 Node* const new_promise_capability = a.LoadContextElement(
616 native_context, Context::NEW_PROMISE_CAPABILITY_INDEX); 637 native_context, Context::NEW_PROMISE_CAPABILITY_INDEX);
617 Node* const capability = 638 Node* const capability =
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
670 typedef compiler::Node Node; 691 typedef compiler::Node Node;
671 692
672 Isolate* isolate = a->isolate(); 693 Isolate* isolate = a->isolate();
673 694
674 Variable var_reason(a, MachineRepresentation::kTagged), 695 Variable var_reason(a, MachineRepresentation::kTagged),
675 var_then(a, MachineRepresentation::kTagged); 696 var_then(a, MachineRepresentation::kTagged);
676 697
677 Label do_enqueue(a), fulfill(a), if_cycle(a, Label::kDeferred), 698 Label do_enqueue(a), fulfill(a), if_cycle(a, Label::kDeferred),
678 if_rejectpromise(a, Label::kDeferred); 699 if_rejectpromise(a, Label::kDeferred);
679 700
701 Label cycle_check(a);
702 a->GotoUnless(a->IsPromiseHookEnabled(), &cycle_check);
703 a->CallRuntime(Runtime::kPromiseHookResolve, context, promise);
704 a->Goto(&cycle_check);
705
706 a->Bind(&cycle_check);
680 // 6. If SameValue(resolution, promise) is true, then 707 // 6. If SameValue(resolution, promise) is true, then
681 a->GotoIf(a->SameValue(promise, result, context), &if_cycle); 708 a->GotoIf(a->SameValue(promise, result, context), &if_cycle);
682 709
683 // 7. If Type(resolution) is not Object, then 710 // 7. If Type(resolution) is not Object, then
684 a->GotoIf(a->TaggedIsSmi(result), &fulfill); 711 a->GotoIf(a->TaggedIsSmi(result), &fulfill);
685 a->GotoUnless(a->IsJSReceiver(result), &fulfill); 712 a->GotoUnless(a->IsJSReceiver(result), &fulfill);
686 713
687 Label if_nativepromise(a), if_notnativepromise(a, Label::kDeferred); 714 Label if_nativepromise(a), if_notnativepromise(a, Label::kDeferred);
688 BranchIfFastPath(a, context, result, &if_nativepromise, &if_notnativepromise); 715 BranchIfFastPath(a, context, result, &if_nativepromise, &if_notnativepromise);
689 716
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
902 a.Return(a.UndefinedConstant()); 929 a.Return(a.UndefinedConstant());
903 } 930 }
904 } 931 }
905 932
906 void Builtins::Generate_PromiseHandle(compiler::CodeAssemblerState* state) { 933 void Builtins::Generate_PromiseHandle(compiler::CodeAssemblerState* state) {
907 CodeStubAssembler a(state); 934 CodeStubAssembler a(state);
908 typedef compiler::Node Node; 935 typedef compiler::Node Node;
909 typedef CodeStubAssembler::Label Label; 936 typedef CodeStubAssembler::Label Label;
910 typedef CodeStubAssembler::Variable Variable; 937 typedef CodeStubAssembler::Variable Variable;
911 938
939 Node* const promise = a.Parameter(1);
912 Node* const value = a.Parameter(2); 940 Node* const value = a.Parameter(2);
913 Node* const handler = a.Parameter(3); 941 Node* const handler = a.Parameter(3);
914 Node* const deferred = a.Parameter(4); 942 Node* const deferred = a.Parameter(4);
915 Node* const context = a.Parameter(7); 943 Node* const context = a.Parameter(7);
916 Isolate* isolate = a.isolate(); 944 Isolate* isolate = a.isolate();
917 945
918 // Get promise from deferred 946 // Get promise from deferred
919 // TODO(gsathya): Remove this lookup by getting rid of the deferred object. 947 // TODO(gsathya): Remove this lookup by getting rid of the deferred object.
920 Callable getproperty_callable = CodeFactory::GetProperty(isolate); 948 Callable getproperty_callable = CodeFactory::GetProperty(isolate);
921 Node* const key = a.HeapConstant(isolate->factory()->promise_string()); 949 Node* const key = a.HeapConstant(isolate->factory()->promise_string());
922 Node* const deferred_promise = 950 Node* const deferred_promise =
923 a.CallStub(getproperty_callable, context, deferred, key); 951 a.CallStub(getproperty_callable, context, deferred, key);
924 952
925 Variable var_reason(&a, MachineRepresentation::kTagged); 953 Variable var_reason(&a, MachineRepresentation::kTagged);
926 954
927 Node* const is_debug_active = a.IsDebugActive(); 955 Node* const is_debug_active = a.IsDebugActive();
928 Label run_handler(&a), if_rejectpromise(&a), debug_push(&a, Label::kDeferred), 956 Label run_handler(&a), if_rejectpromise(&a), debug_push(&a, Label::kDeferred),
929 debug_pop(&a, Label::kDeferred); 957 debug_pop(&a), promisehook_after(&a);
930 a.Branch(is_debug_active, &debug_push, &run_handler); 958
959 a.GotoUnless(a.IsPromiseHookEnabled(), &debug_push);
960 a.CallRuntime(Runtime::kPromiseHookBefore, context, promise);
961 a.Goto(&debug_push);
Dan Ehrenberg 2016/12/15 22:21:48 Nit: It would feel a little cleaner to me if the b
gsathya 2016/12/16 00:55:16 Done.
931 962
932 a.Bind(&debug_push); 963 a.Bind(&debug_push);
933 { 964 {
965 a.GotoUnless(is_debug_active, &run_handler);
934 a.CallRuntime(Runtime::kDebugPushPromise, context, deferred_promise); 966 a.CallRuntime(Runtime::kDebugPushPromise, context, deferred_promise);
935 a.Goto(&run_handler); 967 a.Goto(&run_handler);
936 } 968 }
937 969
938 a.Bind(&run_handler); 970 a.Bind(&run_handler);
939 { 971 {
940 Callable call_callable = CodeFactory::Call(isolate); 972 Callable call_callable = CodeFactory::Call(isolate);
941 973
942 Node* const result = 974 Node* const result =
943 a.CallJS(call_callable, context, handler, a.UndefinedConstant(), value); 975 a.CallJS(call_callable, context, handler, a.UndefinedConstant(), value);
944 976
945 a.GotoIfException(result, &if_rejectpromise, &var_reason); 977 a.GotoIfException(result, &if_rejectpromise, &var_reason);
946 978
947 // TODO(gsathya): Remove this lookup by getting rid of the deferred object. 979 // TODO(gsathya): Remove this lookup by getting rid of the deferred object.
948 Node* const key = a.HeapConstant(isolate->factory()->resolve_string()); 980 Node* const key = a.HeapConstant(isolate->factory()->resolve_string());
949 Node* const on_resolve = 981 Node* const on_resolve =
950 a.CallStub(getproperty_callable, context, deferred, key); 982 a.CallStub(getproperty_callable, context, deferred, key);
951 983
952 Label if_internalhandler(&a), if_customhandler(&a, Label::kDeferred); 984 Label if_internalhandler(&a), if_customhandler(&a, Label::kDeferred);
953 a.Branch(a.IsUndefined(on_resolve), &if_internalhandler, &if_customhandler); 985 a.Branch(a.IsUndefined(on_resolve), &if_internalhandler, &if_customhandler);
954 986
955 a.Bind(&if_internalhandler); 987 a.Bind(&if_internalhandler);
956 InternalResolvePromise(&a, context, deferred_promise, result, &debug_pop); 988 InternalResolvePromise(&a, context, deferred_promise, result,
989 &promisehook_after);
957 990
958 a.Bind(&if_customhandler); 991 a.Bind(&if_customhandler);
959 { 992 {
960 Node* const maybe_exception = a.CallJS(call_callable, context, on_resolve, 993 Node* const maybe_exception = a.CallJS(call_callable, context, on_resolve,
961 a.UndefinedConstant(), result); 994 a.UndefinedConstant(), result);
962 a.GotoIfException(maybe_exception, &if_rejectpromise, &var_reason); 995 a.GotoIfException(maybe_exception, &if_rejectpromise, &var_reason);
963 a.Goto(&debug_pop); 996 a.Goto(&promisehook_after);
964 } 997 }
965 } 998 }
966 999
967 a.Bind(&if_rejectpromise); 1000 a.Bind(&if_rejectpromise);
968 { 1001 {
969 // TODO(gsathya): Remove this lookup by getting rid of the deferred object. 1002 // TODO(gsathya): Remove this lookup by getting rid of the deferred object.
970 Node* const key = a.HeapConstant(isolate->factory()->reject_string()); 1003 Node* const key = a.HeapConstant(isolate->factory()->reject_string());
971 Node* const on_reject = 1004 Node* const on_reject =
972 a.CallStub(getproperty_callable, context, deferred, key); 1005 a.CallStub(getproperty_callable, context, deferred, key);
973 1006
974 Callable promise_handle_reject = CodeFactory::PromiseHandleReject(isolate); 1007 Callable promise_handle_reject = CodeFactory::PromiseHandleReject(isolate);
975 a.CallStub(promise_handle_reject, context, deferred_promise, on_reject, 1008 a.CallStub(promise_handle_reject, context, deferred_promise, on_reject,
976 var_reason.value()); 1009 var_reason.value());
1010 a.Goto(&promisehook_after);
1011 }
1012
1013 a.Bind(&promisehook_after);
1014 {
1015 a.GotoUnless(a.IsPromiseHookEnabled(), &debug_pop);
1016 a.CallRuntime(Runtime::kPromiseHookAfter, context, promise);
977 a.Goto(&debug_pop); 1017 a.Goto(&debug_pop);
978 } 1018 }
979 1019
980 a.Bind(&debug_pop); 1020 a.Bind(&debug_pop);
981 { 1021 {
982 Label out(&a); 1022 Label out(&a);
983
984 a.GotoUnless(is_debug_active, &out); 1023 a.GotoUnless(is_debug_active, &out);
985 a.CallRuntime(Runtime::kDebugPopPromise, context); 1024 a.CallRuntime(Runtime::kDebugPopPromise, context);
986 a.Goto(&out); 1025 a.Goto(&out);
987 1026
988 a.Bind(&out); 1027 a.Bind(&out);
989 a.Return(a.UndefinedConstant()); 1028 a.Return(a.UndefinedConstant());
990 } 1029 }
991 } 1030 }
992 1031
993 } // namespace internal 1032 } // namespace internal
994 } // namespace v8 1033 } // namespace v8
OLDNEW
« no previous file with comments | « src/builtins/builtins.h ('k') | src/code-stub-assembler.cc » ('j') | test/cctest/test-api.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698