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 880 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
891 Heap::kUndefinedValueRootIndex); | 891 Heap::kUndefinedValueRootIndex); |
892 StoreObjectFieldRoot(promise, JSPromise::kFulfillReactionsOffset, | 892 StoreObjectFieldRoot(promise, JSPromise::kFulfillReactionsOffset, |
893 Heap::kUndefinedValueRootIndex); | 893 Heap::kUndefinedValueRootIndex); |
894 StoreObjectFieldRoot(promise, JSPromise::kRejectReactionsOffset, | 894 StoreObjectFieldRoot(promise, JSPromise::kRejectReactionsOffset, |
895 Heap::kUndefinedValueRootIndex); | 895 Heap::kUndefinedValueRootIndex); |
896 } | 896 } |
897 } | 897 } |
898 | 898 |
899 // ES#sec-promise-reject-functions | 899 // ES#sec-promise-reject-functions |
900 // Promise Reject Functions | 900 // Promise Reject Functions |
901 BUILTIN(PromiseRejectClosure) { | 901 TF_BUILTIN(PromiseRejectClosure, PromiseBuiltinsAssembler) { |
902 HandleScope scope(isolate); | 902 Node* const value = Parameter(1); |
| 903 Node* const context = Parameter(4); |
903 | 904 |
904 Handle<Context> context(isolate->context(), isolate); | 905 Label out(this); |
905 | 906 |
906 if (PromiseUtils::HasAlreadyVisited(context)) { | 907 // 3. Let alreadyResolved be F.[[AlreadyResolved]]. |
907 return isolate->heap()->undefined_value(); | 908 int has_already_visited_slot = PromiseUtils::kAlreadyVisitedSlot; |
908 } | |
909 | 909 |
910 PromiseUtils::SetAlreadyVisited(context); | 910 Node* const has_already_visited = |
911 Handle<Object> value = args.atOrUndefined(isolate, 1); | 911 LoadContextElement(context, has_already_visited_slot); |
912 Handle<JSObject> promise = handle(PromiseUtils::GetPromise(context), isolate); | 912 |
913 Handle<Object> debug_event = | 913 // 4. If alreadyResolved.[[Value]] is true, return undefined. |
914 handle(PromiseUtils::GetDebugEvent(context), isolate); | 914 GotoIf(SmiEqual(has_already_visited, SmiConstant(1)), &out); |
915 MaybeHandle<Object> maybe_result; | 915 |
916 Handle<Object> argv[] = {promise, value, debug_event}; | 916 // 5.Set alreadyResolved.[[Value]] to true. |
917 RETURN_FAILURE_ON_EXCEPTION( | 917 StoreContextElementNoWriteBarrier(context, has_already_visited_slot, |
918 isolate, Execution::Call(isolate, isolate->promise_internal_reject(), | 918 SmiConstant(1)); |
919 isolate->factory()->undefined_value(), | 919 |
920 arraysize(argv), argv)); | 920 // 2. Let promise be F.[[Promise]]. |
921 return isolate->heap()->undefined_value(); | 921 Node* const promise = |
| 922 LoadContextElement(context, IntPtrConstant(PromiseUtils::kPromiseSlot)); |
| 923 Node* const debug_event = LoadContextElement( |
| 924 context, IntPtrConstant(PromiseUtils::kDebugEventSlot)); |
| 925 |
| 926 CallRuntime(Runtime::kPromiseReject, context, promise, value, debug_event); |
| 927 Return(UndefinedConstant()); |
| 928 |
| 929 Bind(&out); |
| 930 Return(UndefinedConstant()); |
922 } | 931 } |
923 | 932 |
924 TF_BUILTIN(PromiseConstructor, PromiseBuiltinsAssembler) { | 933 TF_BUILTIN(PromiseConstructor, PromiseBuiltinsAssembler) { |
925 Node* const executor = Parameter(1); | 934 Node* const executor = Parameter(1); |
926 Node* const new_target = Parameter(2); | 935 Node* const new_target = Parameter(2); |
927 Node* const context = Parameter(4); | 936 Node* const context = Parameter(4); |
928 Isolate* isolate = this->isolate(); | 937 Isolate* isolate = this->isolate(); |
929 | 938 |
930 Label if_targetisundefined(this, Label::kDeferred); | 939 Label if_targetisundefined(this, Label::kDeferred); |
931 | 940 |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1030 Return(UndefinedConstant()); // Never reached. | 1039 Return(UndefinedConstant()); // Never reached. |
1031 } | 1040 } |
1032 } | 1041 } |
1033 | 1042 |
1034 TF_BUILTIN(PromiseInternalConstructor, PromiseBuiltinsAssembler) { | 1043 TF_BUILTIN(PromiseInternalConstructor, PromiseBuiltinsAssembler) { |
1035 Node* const parent = Parameter(1); | 1044 Node* const parent = Parameter(1); |
1036 Node* const context = Parameter(4); | 1045 Node* const context = Parameter(4); |
1037 Return(AllocateAndInitJSPromise(context, parent)); | 1046 Return(AllocateAndInitJSPromise(context, parent)); |
1038 } | 1047 } |
1039 | 1048 |
1040 TF_BUILTIN(PromiseCreateAndSet, PromiseBuiltinsAssembler) { | |
1041 Node* const status = Parameter(1); | |
1042 Node* const result = Parameter(2); | |
1043 Node* const context = Parameter(5); | |
1044 | |
1045 Node* const instance = AllocateAndSetJSPromise(context, status, result); | |
1046 Return(instance); | |
1047 } | |
1048 | |
1049 TF_BUILTIN(IsPromise, PromiseBuiltinsAssembler) { | 1049 TF_BUILTIN(IsPromise, PromiseBuiltinsAssembler) { |
1050 Node* const maybe_promise = Parameter(1); | 1050 Node* const maybe_promise = Parameter(1); |
1051 Label if_notpromise(this, Label::kDeferred); | 1051 Label if_notpromise(this, Label::kDeferred); |
1052 | 1052 |
1053 GotoIf(TaggedIsSmi(maybe_promise), &if_notpromise); | 1053 GotoIf(TaggedIsSmi(maybe_promise), &if_notpromise); |
1054 | 1054 |
1055 Node* const result = | 1055 Node* const result = |
1056 SelectBooleanConstant(HasInstanceType(maybe_promise, JS_PROMISE_TYPE)); | 1056 SelectBooleanConstant(HasInstanceType(maybe_promise, JS_PROMISE_TYPE)); |
1057 Return(result); | 1057 Return(result); |
1058 | 1058 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1093 | 1093 |
1094 // ES#sec-promise-resolve-functions | 1094 // ES#sec-promise-resolve-functions |
1095 // Promise Resolve Functions | 1095 // Promise Resolve Functions |
1096 TF_BUILTIN(PromiseResolveClosure, PromiseBuiltinsAssembler) { | 1096 TF_BUILTIN(PromiseResolveClosure, PromiseBuiltinsAssembler) { |
1097 Node* const value = Parameter(1); | 1097 Node* const value = Parameter(1); |
1098 Node* const context = Parameter(4); | 1098 Node* const context = Parameter(4); |
1099 | 1099 |
1100 Label out(this); | 1100 Label out(this); |
1101 | 1101 |
1102 // 3. Let alreadyResolved be F.[[AlreadyResolved]]. | 1102 // 3. Let alreadyResolved be F.[[AlreadyResolved]]. |
1103 Node* const has_already_visited_slot = | 1103 int has_already_visited_slot = PromiseUtils::kAlreadyVisitedSlot; |
1104 IntPtrConstant(PromiseUtils::kAlreadyVisitedSlot); | |
1105 | 1104 |
1106 Node* const has_already_visited = | 1105 Node* const has_already_visited = |
1107 LoadFixedArrayElement(context, has_already_visited_slot); | 1106 LoadContextElement(context, has_already_visited_slot); |
1108 | 1107 |
1109 // 4. If alreadyResolved.[[Value]] is true, return undefined. | 1108 // 4. If alreadyResolved.[[Value]] is true, return undefined. |
1110 GotoIf(SmiEqual(has_already_visited, SmiConstant(1)), &out); | 1109 GotoIf(SmiEqual(has_already_visited, SmiConstant(1)), &out); |
1111 | 1110 |
1112 // 5.Set alreadyResolved.[[Value]] to true. | 1111 // 5.Set alreadyResolved.[[Value]] to true. |
1113 StoreFixedArrayElement(context, has_already_visited_slot, SmiConstant(1)); | 1112 StoreContextElementNoWriteBarrier(context, has_already_visited_slot, |
| 1113 SmiConstant(1)); |
1114 | 1114 |
1115 // 2. Let promise be F.[[Promise]]. | 1115 // 2. Let promise be F.[[Promise]]. |
1116 Node* const promise = LoadFixedArrayElement( | 1116 Node* const promise = |
1117 context, IntPtrConstant(PromiseUtils::kPromiseSlot)); | 1117 LoadContextElement(context, IntPtrConstant(PromiseUtils::kPromiseSlot)); |
1118 | 1118 |
1119 InternalResolvePromise(context, promise, value); | 1119 InternalResolvePromise(context, promise, value); |
1120 Return(UndefinedConstant()); | 1120 Return(UndefinedConstant()); |
1121 | 1121 |
1122 Bind(&out); | 1122 Bind(&out); |
1123 Return(UndefinedConstant()); | 1123 Return(UndefinedConstant()); |
1124 } | 1124 } |
1125 | 1125 |
1126 TF_BUILTIN(ResolvePromise, PromiseBuiltinsAssembler) { | 1126 TF_BUILTIN(ResolvePromise, PromiseBuiltinsAssembler) { |
1127 Node* const promise = Parameter(1); | 1127 Node* const promise = Parameter(1); |
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1395 TF_BUILTIN(NewPromiseCapability, PromiseBuiltinsAssembler) { | 1395 TF_BUILTIN(NewPromiseCapability, PromiseBuiltinsAssembler) { |
1396 Node* constructor = Parameter(1); | 1396 Node* constructor = Parameter(1); |
1397 Node* debug_event = Parameter(2); | 1397 Node* debug_event = Parameter(2); |
1398 Node* context = Parameter(5); | 1398 Node* context = Parameter(5); |
1399 | 1399 |
1400 CSA_ASSERT_JS_ARGC_EQ(this, 2); | 1400 CSA_ASSERT_JS_ARGC_EQ(this, 2); |
1401 | 1401 |
1402 Return(NewPromiseCapability(context, constructor, debug_event)); | 1402 Return(NewPromiseCapability(context, constructor, debug_event)); |
1403 } | 1403 } |
1404 | 1404 |
| 1405 TF_BUILTIN(PromiseReject, PromiseBuiltinsAssembler) { |
| 1406 // 1. Let C be the this value. |
| 1407 Node* const receiver = Parameter(0); |
| 1408 Node* const reason = Parameter(1); |
| 1409 Node* const context = Parameter(4); |
| 1410 |
| 1411 // 2. If Type(C) is not Object, throw a TypeError exception. |
| 1412 ThrowIfNotJSReceiver(context, receiver, MessageTemplate::kCalledOnNonObject, |
| 1413 "PromiseReject"); |
| 1414 |
| 1415 Label if_nativepromise(this), if_custompromise(this, Label::kDeferred); |
| 1416 Node* const native_context = LoadNativeContext(context); |
| 1417 Node* const promise_fun = |
| 1418 LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX); |
| 1419 Branch(WordEqual(promise_fun, receiver), &if_nativepromise, |
| 1420 &if_custompromise); |
| 1421 |
| 1422 Bind(&if_nativepromise); |
| 1423 { |
| 1424 Node* const promise = AllocateAndSetJSPromise( |
| 1425 context, SmiConstant(v8::Promise::kRejected), reason); |
| 1426 CallRuntime(Runtime::kPromiseRejectEventFromStack, context, promise, |
| 1427 reason); |
| 1428 Return(promise); |
| 1429 } |
| 1430 |
| 1431 Bind(&if_custompromise); |
| 1432 { |
| 1433 // 3. Let promiseCapability be ? NewPromiseCapability(C). |
| 1434 Node* const capability = NewPromiseCapability(context, receiver); |
| 1435 |
| 1436 // 4. Perform ? Call(promiseCapability.[[Reject]], undefined, « r »). |
| 1437 Node* const reject = |
| 1438 LoadObjectField(capability, JSPromiseCapability::kRejectOffset); |
| 1439 Callable call_callable = CodeFactory::Call(isolate()); |
| 1440 CallJS(call_callable, context, reject, UndefinedConstant(), reason); |
| 1441 |
| 1442 // 5. Return promiseCapability.[[Promise]]. |
| 1443 Node* const promise = |
| 1444 LoadObjectField(capability, JSPromiseCapability::kPromiseOffset); |
| 1445 Return(promise); |
| 1446 } |
| 1447 } |
| 1448 |
1405 } // namespace internal | 1449 } // namespace internal |
1406 } // namespace v8 | 1450 } // namespace v8 |
OLD | NEW |