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...) 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...) 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...) 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, | |
Igor Sheludko
2017/01/17 11:54:13
I think you can merge this with the InternalPromis
gsathya
2017/01/17 14:51:34
Done.
| |
945 Node* promise, Node* value, | |
946 bool debug_event) { | |
947 Label out(this); | |
948 | |
949 if (debug_event) { | |
950 GotoUnless(IsDebugActive(), &out); | |
951 CallRuntime(Runtime::kDebugPromiseReject, context, promise, value); | |
952 Goto(&out); | |
953 } else { | |
954 Goto(&out); | |
955 } | |
956 | |
957 Bind(&out); | |
958 InternalPromiseReject(context, promise, value); | |
959 } | |
960 | |
961 void PromiseBuiltinsAssembler::InternalPromiseReject(Node* context, | |
962 Node* promise, Node* value, | |
963 Node* debug_event) { | |
964 Label out(this); | |
965 GotoUnless(IsDebugActive(), &out); | |
966 GotoUnless(WordEqual(TrueConstant(), debug_event), &out); | |
967 CallRuntime(Runtime::kDebugPromiseReject, context, promise, value); | |
968 Goto(&out); | |
969 | |
970 Bind(&out); | |
971 InternalPromiseReject(context, promise, value); | |
Igor Sheludko
2017/01/17 11:54:14
... and call InternalPromiseReject(context, promis
gsathya
2017/01/17 14:51:34
Done.
| |
972 } | |
973 | |
974 // This duplicates a lot of logic from PromiseRejectEvent in | |
975 // runtime-promise.cc | |
976 void PromiseBuiltinsAssembler::InternalPromiseReject(Node* context, | |
977 Node* promise, | |
978 Node* value) { | |
979 Label fulfill(this), report_unhandledpromise(this), | |
980 run_promise_hook(this, Label::kDeferred); | |
981 | |
982 Branch(IsPromiseHookEnabled(), &run_promise_hook, &report_unhandledpromise); | |
983 | |
984 Bind(&run_promise_hook); | |
985 { | |
986 CallRuntime(Runtime::kPromiseHookResolve, context, promise); | |
987 Goto(&report_unhandledpromise); | |
988 } | |
989 | |
990 Bind(&report_unhandledpromise); | |
991 { | |
992 GotoIf(PromiseHasHandler(promise), &fulfill); | |
993 CallRuntime(Runtime::kReportPromiseReject, context, promise, value); | |
994 Goto(&fulfill); | |
995 } | |
996 | |
997 Bind(&fulfill); | |
998 PromiseFulfill(context, promise, value, v8::Promise::kRejected); | |
999 } | |
1000 | |
946 // ES#sec-promise-reject-functions | 1001 // ES#sec-promise-reject-functions |
947 // Promise Reject Functions | 1002 // Promise Reject Functions |
948 TF_BUILTIN(PromiseRejectClosure, PromiseBuiltinsAssembler) { | 1003 TF_BUILTIN(PromiseRejectClosure, PromiseBuiltinsAssembler) { |
949 Node* const value = Parameter(1); | 1004 Node* const value = Parameter(1); |
950 Node* const context = Parameter(4); | 1005 Node* const context = Parameter(4); |
951 | 1006 |
952 Label out(this); | 1007 Label out(this); |
953 | 1008 |
954 // 3. Let alreadyResolved be F.[[AlreadyResolved]]. | 1009 // 3. Let alreadyResolved be F.[[AlreadyResolved]]. |
955 int has_already_visited_slot = PromiseUtils::kAlreadyVisitedSlot; | 1010 int has_already_visited_slot = PromiseUtils::kAlreadyVisitedSlot; |
956 | 1011 |
957 Node* const has_already_visited = | 1012 Node* const has_already_visited = |
958 LoadContextElement(context, has_already_visited_slot); | 1013 LoadContextElement(context, has_already_visited_slot); |
959 | 1014 |
960 // 4. If alreadyResolved.[[Value]] is true, return undefined. | 1015 // 4. If alreadyResolved.[[Value]] is true, return undefined. |
961 GotoIf(SmiEqual(has_already_visited, SmiConstant(1)), &out); | 1016 GotoIf(SmiEqual(has_already_visited, SmiConstant(1)), &out); |
962 | 1017 |
963 // 5.Set alreadyResolved.[[Value]] to true. | 1018 // 5.Set alreadyResolved.[[Value]] to true. |
964 StoreContextElementNoWriteBarrier(context, has_already_visited_slot, | 1019 StoreContextElementNoWriteBarrier(context, has_already_visited_slot, |
965 SmiConstant(1)); | 1020 SmiConstant(1)); |
966 | 1021 |
967 // 2. Let promise be F.[[Promise]]. | 1022 // 2. Let promise be F.[[Promise]]. |
968 Node* const promise = | 1023 Node* const promise = |
969 LoadContextElement(context, IntPtrConstant(PromiseUtils::kPromiseSlot)); | 1024 LoadContextElement(context, IntPtrConstant(PromiseUtils::kPromiseSlot)); |
970 Node* const debug_event = LoadContextElement( | 1025 Node* const debug_event = LoadContextElement( |
971 context, IntPtrConstant(PromiseUtils::kDebugEventSlot)); | 1026 context, IntPtrConstant(PromiseUtils::kDebugEventSlot)); |
972 | 1027 |
973 CallRuntime(Runtime::kPromiseReject, context, promise, value, debug_event); | 1028 InternalPromiseReject(context, promise, value, debug_event); |
974 Return(UndefinedConstant()); | 1029 Return(UndefinedConstant()); |
975 | 1030 |
976 Bind(&out); | 1031 Bind(&out); |
977 Return(UndefinedConstant()); | 1032 Return(UndefinedConstant()); |
978 } | 1033 } |
979 | 1034 |
980 TF_BUILTIN(PromiseConstructor, PromiseBuiltinsAssembler) { | 1035 TF_BUILTIN(PromiseConstructor, PromiseBuiltinsAssembler) { |
981 Node* const executor = Parameter(1); | 1036 Node* const executor = Parameter(1); |
982 Node* const new_target = Parameter(2); | 1037 Node* const new_target = Parameter(2); |
983 Node* const context = Parameter(4); | 1038 Node* const context = Parameter(4); |
(...skipping 216 matching lines...) Loading... | |
1200 Node* const context = Parameter(Descriptor::kContext); | 1255 Node* const context = Parameter(Descriptor::kContext); |
1201 | 1256 |
1202 Callable call_callable = CodeFactory::Call(isolate()); | 1257 Callable call_callable = CodeFactory::Call(isolate()); |
1203 Variable var_unused(this, MachineRepresentation::kTagged); | 1258 Variable var_unused(this, MachineRepresentation::kTagged); |
1204 | 1259 |
1205 Label if_internalhandler(this), if_customhandler(this, Label::kDeferred); | 1260 Label if_internalhandler(this), if_customhandler(this, Label::kDeferred); |
1206 Branch(IsUndefined(on_reject), &if_internalhandler, &if_customhandler); | 1261 Branch(IsUndefined(on_reject), &if_internalhandler, &if_customhandler); |
1207 | 1262 |
1208 Bind(&if_internalhandler); | 1263 Bind(&if_internalhandler); |
1209 { | 1264 { |
1210 CallRuntime(Runtime::kPromiseReject, context, promise, exception, | 1265 InternalPromiseReject(context, promise, exception, false); |
1211 FalseConstant()); | |
1212 Return(UndefinedConstant()); | 1266 Return(UndefinedConstant()); |
1213 } | 1267 } |
1214 | 1268 |
1215 Bind(&if_customhandler); | 1269 Bind(&if_customhandler); |
1216 { | 1270 { |
1217 CallJS(call_callable, context, on_reject, UndefinedConstant(), exception); | 1271 CallJS(call_callable, context, on_reject, UndefinedConstant(), exception); |
1218 Return(UndefinedConstant()); | 1272 Return(UndefinedConstant()); |
1219 } | 1273 } |
1220 } | 1274 } |
1221 | 1275 |
(...skipping 275 matching lines...) Loading... | |
1497 Callable call_callable = CodeFactory::Call(isolate()); | 1551 Callable call_callable = CodeFactory::Call(isolate()); |
1498 CallJS(call_callable, context, reject, UndefinedConstant(), reason); | 1552 CallJS(call_callable, context, reject, UndefinedConstant(), reason); |
1499 | 1553 |
1500 // 5. Return promiseCapability.[[Promise]]. | 1554 // 5. Return promiseCapability.[[Promise]]. |
1501 Node* const promise = | 1555 Node* const promise = |
1502 LoadObjectField(capability, JSPromiseCapability::kPromiseOffset); | 1556 LoadObjectField(capability, JSPromiseCapability::kPromiseOffset); |
1503 Return(promise); | 1557 Return(promise); |
1504 } | 1558 } |
1505 } | 1559 } |
1506 | 1560 |
1561 TF_BUILTIN(InternalPromiseReject, PromiseBuiltinsAssembler) { | |
1562 Node* const promise = Parameter(1); | |
1563 Node* const reason = Parameter(2); | |
1564 Node* const debug_event = Parameter(3); | |
1565 Node* const context = Parameter(6); | |
1566 | |
1567 InternalPromiseReject(context, promise, reason, debug_event); | |
1568 Return(UndefinedConstant()); | |
1569 } | |
1570 | |
1507 } // namespace internal | 1571 } // namespace internal |
1508 } // namespace v8 | 1572 } // namespace v8 |
OLD | NEW |