Chromium Code Reviews| 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 |