| 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-promise.h" | 5 #include "src/builtins/builtins-promise.h" |
| 6 #include "src/builtins/builtins-constructor.h" | 6 #include "src/builtins/builtins-constructor.h" |
| 7 #include "src/builtins/builtins-utils.h" | 7 #include "src/builtins/builtins-utils.h" |
| 8 #include "src/builtins/builtins.h" | 8 #include "src/builtins/builtins.h" |
| 9 #include "src/code-factory.h" | 9 #include "src/code-factory.h" |
| 10 #include "src/code-stub-assembler.h" | 10 #include "src/code-stub-assembler.h" |
| (...skipping 730 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 741 Node* const has_handler = PromiseHasHandler(result); | 741 Node* const has_handler = PromiseHasHandler(result); |
| 742 | 742 |
| 743 // Promise has already been rejected, but had no handler. | 743 // Promise has already been rejected, but had no handler. |
| 744 // Revoke previously triggered reject event. | 744 // Revoke previously triggered reject event. |
| 745 GotoIf(has_handler, &reject); | 745 GotoIf(has_handler, &reject); |
| 746 CallRuntime(Runtime::kPromiseRevokeReject, context, result); | 746 CallRuntime(Runtime::kPromiseRevokeReject, context, result); |
| 747 Goto(&reject); | 747 Goto(&reject); |
| 748 | 748 |
| 749 Bind(&reject); | 749 Bind(&reject); |
| 750 // Don't cause a debug event as this case is forwarding a rejection | 750 // Don't cause a debug event as this case is forwarding a rejection |
| 751 CallRuntime(Runtime::kPromiseReject, context, promise, thenable_value, | 751 InternalPromiseReject(context, promise, thenable_value, false); |
| 752 FalseConstant()); | |
| 753 PromiseSetHasHandler(result); | 752 PromiseSetHasHandler(result); |
| 754 Goto(&out); | 753 Goto(&out); |
| 755 } | 754 } |
| 756 } | 755 } |
| 757 } | 756 } |
| 758 | 757 |
| 759 Bind(&if_notnativepromise); | 758 Bind(&if_notnativepromise); |
| 760 { | 759 { |
| 761 // 8. Let then be Get(resolution, "then"). | 760 // 8. Let then be Get(resolution, "then"). |
| 762 Node* const then_str = HeapConstant(isolate->factory()->then_string()); | 761 Node* const then_str = HeapConstant(isolate->factory()->then_string()); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 829 CallRuntime(Runtime::kNewTypeError, context, message_id, result); | 828 CallRuntime(Runtime::kNewTypeError, context, message_id, result); |
| 830 var_reason.Bind(error); | 829 var_reason.Bind(error); |
| 831 | 830 |
| 832 // 6.b Return RejectPromise(promise, selfResolutionError). | 831 // 6.b Return RejectPromise(promise, selfResolutionError). |
| 833 Goto(&if_rejectpromise); | 832 Goto(&if_rejectpromise); |
| 834 } | 833 } |
| 835 | 834 |
| 836 // 9.a Return RejectPromise(promise, then.[[Value]]). | 835 // 9.a Return RejectPromise(promise, then.[[Value]]). |
| 837 Bind(&if_rejectpromise); | 836 Bind(&if_rejectpromise); |
| 838 { | 837 { |
| 839 CallRuntime(Runtime::kPromiseReject, context, promise, var_reason.value(), | 838 InternalPromiseReject(context, promise, var_reason.value(), true); |
| 840 TrueConstant()); | |
| 841 Goto(&out); | 839 Goto(&out); |
| 842 } | 840 } |
| 843 | 841 |
| 844 Bind(&out); | 842 Bind(&out); |
| 845 } | 843 } |
| 846 | 844 |
| 847 void PromiseBuiltinsAssembler::PromiseFulfill( | 845 void PromiseBuiltinsAssembler::PromiseFulfill( |
| 848 Node* context, Node* promise, Node* result, | 846 Node* context, Node* promise, Node* result, |
| 849 v8::Promise::PromiseState status) { | 847 v8::Promise::PromiseState status) { |
| 850 Label do_promisereset(this), debug_async_event_enqueue_recurring(this); | 848 Label do_promisereset(this), debug_async_event_enqueue_recurring(this); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 936 { | 934 { |
| 937 Branch(WordEqual(CallRuntime(Runtime::kAllowDynamicFunction, context, | 935 Branch(WordEqual(CallRuntime(Runtime::kAllowDynamicFunction, context, |
| 938 promise_constructor), | 936 promise_constructor), |
| 939 BooleanConstant(true)), | 937 BooleanConstant(true)), |
| 940 &has_access, if_noaccess); | 938 &has_access, if_noaccess); |
| 941 } | 939 } |
| 942 | 940 |
| 943 Bind(&has_access); | 941 Bind(&has_access); |
| 944 } | 942 } |
| 945 | 943 |
| 944 void PromiseBuiltinsAssembler::InternalPromiseReject(Node* context, |
| 945 Node* promise, Node* value, |
| 946 Node* debug_event) { |
| 947 Label out(this); |
| 948 GotoUnless(IsDebugActive(), &out); |
| 949 GotoUnless(WordEqual(TrueConstant(), debug_event), &out); |
| 950 CallRuntime(Runtime::kDebugPromiseReject, context, promise, value); |
| 951 Goto(&out); |
| 952 |
| 953 Bind(&out); |
| 954 InternalPromiseReject(context, promise, value, false); |
| 955 } |
| 956 |
| 957 // This duplicates a lot of logic from PromiseRejectEvent in |
| 958 // runtime-promise.cc |
| 959 void PromiseBuiltinsAssembler::InternalPromiseReject(Node* context, |
| 960 Node* promise, Node* value, |
| 961 bool debug_event) { |
| 962 Label fulfill(this), report_unhandledpromise(this), run_promise_hook(this); |
| 963 |
| 964 if (debug_event) { |
| 965 GotoUnless(IsDebugActive(), &run_promise_hook); |
| 966 CallRuntime(Runtime::kDebugPromiseReject, context, promise, value); |
| 967 Goto(&run_promise_hook); |
| 968 } else { |
| 969 Goto(&run_promise_hook); |
| 970 } |
| 971 |
| 972 Bind(&run_promise_hook); |
| 973 { |
| 974 GotoUnless(IsPromiseHookEnabled(), &report_unhandledpromise); |
| 975 CallRuntime(Runtime::kPromiseHookResolve, context, promise); |
| 976 Goto(&report_unhandledpromise); |
| 977 } |
| 978 |
| 979 Bind(&report_unhandledpromise); |
| 980 { |
| 981 GotoIf(PromiseHasHandler(promise), &fulfill); |
| 982 CallRuntime(Runtime::kReportPromiseReject, context, promise, value); |
| 983 Goto(&fulfill); |
| 984 } |
| 985 |
| 986 Bind(&fulfill); |
| 987 PromiseFulfill(context, promise, value, v8::Promise::kRejected); |
| 988 } |
| 989 |
| 946 // ES#sec-promise-reject-functions | 990 // ES#sec-promise-reject-functions |
| 947 // Promise Reject Functions | 991 // Promise Reject Functions |
| 948 TF_BUILTIN(PromiseRejectClosure, PromiseBuiltinsAssembler) { | 992 TF_BUILTIN(PromiseRejectClosure, PromiseBuiltinsAssembler) { |
| 949 Node* const value = Parameter(1); | 993 Node* const value = Parameter(1); |
| 950 Node* const context = Parameter(4); | 994 Node* const context = Parameter(4); |
| 951 | 995 |
| 952 Label out(this); | 996 Label out(this); |
| 953 | 997 |
| 954 // 3. Let alreadyResolved be F.[[AlreadyResolved]]. | 998 // 3. Let alreadyResolved be F.[[AlreadyResolved]]. |
| 955 int has_already_visited_slot = PromiseUtils::kAlreadyVisitedSlot; | 999 int has_already_visited_slot = PromiseUtils::kAlreadyVisitedSlot; |
| 956 | 1000 |
| 957 Node* const has_already_visited = | 1001 Node* const has_already_visited = |
| 958 LoadContextElement(context, has_already_visited_slot); | 1002 LoadContextElement(context, has_already_visited_slot); |
| 959 | 1003 |
| 960 // 4. If alreadyResolved.[[Value]] is true, return undefined. | 1004 // 4. If alreadyResolved.[[Value]] is true, return undefined. |
| 961 GotoIf(SmiEqual(has_already_visited, SmiConstant(1)), &out); | 1005 GotoIf(SmiEqual(has_already_visited, SmiConstant(1)), &out); |
| 962 | 1006 |
| 963 // 5.Set alreadyResolved.[[Value]] to true. | 1007 // 5.Set alreadyResolved.[[Value]] to true. |
| 964 StoreContextElementNoWriteBarrier(context, has_already_visited_slot, | 1008 StoreContextElementNoWriteBarrier(context, has_already_visited_slot, |
| 965 SmiConstant(1)); | 1009 SmiConstant(1)); |
| 966 | 1010 |
| 967 // 2. Let promise be F.[[Promise]]. | 1011 // 2. Let promise be F.[[Promise]]. |
| 968 Node* const promise = | 1012 Node* const promise = |
| 969 LoadContextElement(context, IntPtrConstant(PromiseUtils::kPromiseSlot)); | 1013 LoadContextElement(context, IntPtrConstant(PromiseUtils::kPromiseSlot)); |
| 970 Node* const debug_event = LoadContextElement( | 1014 Node* const debug_event = LoadContextElement( |
| 971 context, IntPtrConstant(PromiseUtils::kDebugEventSlot)); | 1015 context, IntPtrConstant(PromiseUtils::kDebugEventSlot)); |
| 972 | 1016 |
| 973 CallRuntime(Runtime::kPromiseReject, context, promise, value, debug_event); | 1017 InternalPromiseReject(context, promise, value, debug_event); |
| 974 Return(UndefinedConstant()); | 1018 Return(UndefinedConstant()); |
| 975 | 1019 |
| 976 Bind(&out); | 1020 Bind(&out); |
| 977 Return(UndefinedConstant()); | 1021 Return(UndefinedConstant()); |
| 978 } | 1022 } |
| 979 | 1023 |
| 980 TF_BUILTIN(PromiseConstructor, PromiseBuiltinsAssembler) { | 1024 TF_BUILTIN(PromiseConstructor, PromiseBuiltinsAssembler) { |
| 981 Node* const executor = Parameter(1); | 1025 Node* const executor = Parameter(1); |
| 982 Node* const new_target = Parameter(2); | 1026 Node* const new_target = Parameter(2); |
| 983 Node* const context = Parameter(4); | 1027 Node* const context = Parameter(4); |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1200 Node* const context = Parameter(Descriptor::kContext); | 1244 Node* const context = Parameter(Descriptor::kContext); |
| 1201 | 1245 |
| 1202 Callable call_callable = CodeFactory::Call(isolate()); | 1246 Callable call_callable = CodeFactory::Call(isolate()); |
| 1203 Variable var_unused(this, MachineRepresentation::kTagged); | 1247 Variable var_unused(this, MachineRepresentation::kTagged); |
| 1204 | 1248 |
| 1205 Label if_internalhandler(this), if_customhandler(this, Label::kDeferred); | 1249 Label if_internalhandler(this), if_customhandler(this, Label::kDeferred); |
| 1206 Branch(IsUndefined(on_reject), &if_internalhandler, &if_customhandler); | 1250 Branch(IsUndefined(on_reject), &if_internalhandler, &if_customhandler); |
| 1207 | 1251 |
| 1208 Bind(&if_internalhandler); | 1252 Bind(&if_internalhandler); |
| 1209 { | 1253 { |
| 1210 CallRuntime(Runtime::kPromiseReject, context, promise, exception, | 1254 InternalPromiseReject(context, promise, exception, false); |
| 1211 FalseConstant()); | |
| 1212 Return(UndefinedConstant()); | 1255 Return(UndefinedConstant()); |
| 1213 } | 1256 } |
| 1214 | 1257 |
| 1215 Bind(&if_customhandler); | 1258 Bind(&if_customhandler); |
| 1216 { | 1259 { |
| 1217 CallJS(call_callable, context, on_reject, UndefinedConstant(), exception); | 1260 CallJS(call_callable, context, on_reject, UndefinedConstant(), exception); |
| 1218 Return(UndefinedConstant()); | 1261 Return(UndefinedConstant()); |
| 1219 } | 1262 } |
| 1220 } | 1263 } |
| 1221 | 1264 |
| (...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1497 Callable call_callable = CodeFactory::Call(isolate()); | 1540 Callable call_callable = CodeFactory::Call(isolate()); |
| 1498 CallJS(call_callable, context, reject, UndefinedConstant(), reason); | 1541 CallJS(call_callable, context, reject, UndefinedConstant(), reason); |
| 1499 | 1542 |
| 1500 // 5. Return promiseCapability.[[Promise]]. | 1543 // 5. Return promiseCapability.[[Promise]]. |
| 1501 Node* const promise = | 1544 Node* const promise = |
| 1502 LoadObjectField(capability, JSPromiseCapability::kPromiseOffset); | 1545 LoadObjectField(capability, JSPromiseCapability::kPromiseOffset); |
| 1503 Return(promise); | 1546 Return(promise); |
| 1504 } | 1547 } |
| 1505 } | 1548 } |
| 1506 | 1549 |
| 1550 TF_BUILTIN(InternalPromiseReject, PromiseBuiltinsAssembler) { |
| 1551 Node* const promise = Parameter(1); |
| 1552 Node* const reason = Parameter(2); |
| 1553 Node* const debug_event = Parameter(3); |
| 1554 Node* const context = Parameter(6); |
| 1555 |
| 1556 InternalPromiseReject(context, promise, reason, debug_event); |
| 1557 Return(UndefinedConstant()); |
| 1558 } |
| 1559 |
| 1507 } // namespace internal | 1560 } // namespace internal |
| 1508 } // namespace v8 | 1561 } // namespace v8 |
| OLD | NEW |