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 | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |