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 886 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
897 Heap::kUndefinedValueRootIndex); | 897 Heap::kUndefinedValueRootIndex); |
898 StoreObjectFieldRoot(promise, JSPromise::kDeferredOnRejectOffset, | 898 StoreObjectFieldRoot(promise, JSPromise::kDeferredOnRejectOffset, |
899 Heap::kUndefinedValueRootIndex); | 899 Heap::kUndefinedValueRootIndex); |
900 StoreObjectFieldRoot(promise, JSPromise::kFulfillReactionsOffset, | 900 StoreObjectFieldRoot(promise, JSPromise::kFulfillReactionsOffset, |
901 Heap::kUndefinedValueRootIndex); | 901 Heap::kUndefinedValueRootIndex); |
902 StoreObjectFieldRoot(promise, JSPromise::kRejectReactionsOffset, | 902 StoreObjectFieldRoot(promise, JSPromise::kRejectReactionsOffset, |
903 Heap::kUndefinedValueRootIndex); | 903 Heap::kUndefinedValueRootIndex); |
904 } | 904 } |
905 } | 905 } |
906 | 906 |
| 907 void PromiseBuiltinsAssembler::BranchIfAccessCheckFailed( |
| 908 Node* context, Node* native_context, Node* promise_constructor, |
| 909 Node* executor, Label* if_noaccess) { |
| 910 Variable var_executor(this, MachineRepresentation::kTagged); |
| 911 var_executor.Bind(executor); |
| 912 Label has_access(this), call_runtime(this, Label::kDeferred); |
| 913 |
| 914 // If executor is a bound function, load the bound function until we've |
| 915 // reached an actual function. |
| 916 Label found_function(this), loop_over_bound_function(this, &var_executor); |
| 917 Goto(&loop_over_bound_function); |
| 918 Bind(&loop_over_bound_function); |
| 919 { |
| 920 Node* executor_type = LoadInstanceType(var_executor.value()); |
| 921 GotoIf(InstanceTypeEqual(executor_type, JS_FUNCTION_TYPE), &found_function); |
| 922 GotoUnless(InstanceTypeEqual(executor_type, JS_BOUND_FUNCTION_TYPE), |
| 923 &call_runtime); |
| 924 var_executor.Bind(LoadObjectField( |
| 925 var_executor.value(), JSBoundFunction::kBoundTargetFunctionOffset)); |
| 926 Goto(&loop_over_bound_function); |
| 927 } |
| 928 |
| 929 // Load the context from the function and compare it to the Promise |
| 930 // constructor's context. If they match, everything is fine, otherwise, bail |
| 931 // out to the runtime. |
| 932 Bind(&found_function); |
| 933 { |
| 934 Node* function_context = |
| 935 LoadObjectField(var_executor.value(), JSFunction::kContextOffset); |
| 936 Node* native_function_context = LoadNativeContext(function_context); |
| 937 Branch(WordEqual(native_context, native_function_context), &has_access, |
| 938 &call_runtime); |
| 939 } |
| 940 |
| 941 Bind(&call_runtime); |
| 942 { |
| 943 Branch(WordEqual(CallRuntime(Runtime::kAllowDynamicFunction, context, |
| 944 promise_constructor), |
| 945 BooleanConstant(true)), |
| 946 &has_access, if_noaccess); |
| 947 } |
| 948 |
| 949 Bind(&has_access); |
| 950 } |
| 951 |
907 // ES#sec-promise-reject-functions | 952 // ES#sec-promise-reject-functions |
908 // Promise Reject Functions | 953 // Promise Reject Functions |
909 TF_BUILTIN(PromiseRejectClosure, PromiseBuiltinsAssembler) { | 954 TF_BUILTIN(PromiseRejectClosure, PromiseBuiltinsAssembler) { |
910 Node* const value = Parameter(1); | 955 Node* const value = Parameter(1); |
911 Node* const context = Parameter(4); | 956 Node* const context = Parameter(4); |
912 | 957 |
913 Label out(this); | 958 Label out(this); |
914 | 959 |
915 // 3. Let alreadyResolved be F.[[AlreadyResolved]]. | 960 // 3. Let alreadyResolved be F.[[AlreadyResolved]]. |
916 int has_already_visited_slot = PromiseUtils::kAlreadyVisitedSlot; | 961 int has_already_visited_slot = PromiseUtils::kAlreadyVisitedSlot; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
954 | 999 |
955 Node* const executor_map = LoadMap(executor); | 1000 Node* const executor_map = LoadMap(executor); |
956 GotoUnless(IsCallableMap(executor_map), &if_notcallable); | 1001 GotoUnless(IsCallableMap(executor_map), &if_notcallable); |
957 | 1002 |
958 Node* const native_context = LoadNativeContext(context); | 1003 Node* const native_context = LoadNativeContext(context); |
959 Node* const promise_fun = | 1004 Node* const promise_fun = |
960 LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX); | 1005 LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX); |
961 Node* const is_debug_active = IsDebugActive(); | 1006 Node* const is_debug_active = IsDebugActive(); |
962 Label if_targetisnotmodified(this), | 1007 Label if_targetisnotmodified(this), |
963 if_targetismodified(this, Label::kDeferred), run_executor(this), | 1008 if_targetismodified(this, Label::kDeferred), run_executor(this), |
964 debug_push(this); | 1009 debug_push(this), if_noaccess(this, Label::kDeferred); |
| 1010 |
| 1011 BranchIfAccessCheckFailed(context, native_context, promise_fun, executor, |
| 1012 &if_noaccess); |
965 | 1013 |
966 Branch(WordEqual(promise_fun, new_target), &if_targetisnotmodified, | 1014 Branch(WordEqual(promise_fun, new_target), &if_targetisnotmodified, |
967 &if_targetismodified); | 1015 &if_targetismodified); |
968 | 1016 |
969 Variable var_result(this, MachineRepresentation::kTagged), | 1017 Variable var_result(this, MachineRepresentation::kTagged), |
970 var_reject_call(this, MachineRepresentation::kTagged), | 1018 var_reject_call(this, MachineRepresentation::kTagged), |
971 var_reason(this, MachineRepresentation::kTagged); | 1019 var_reason(this, MachineRepresentation::kTagged); |
972 | 1020 |
973 Bind(&if_targetisnotmodified); | 1021 Bind(&if_targetisnotmodified); |
974 { | 1022 { |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1039 } | 1087 } |
1040 | 1088 |
1041 // 2. If IsCallable(executor) is false, throw a TypeError exception. | 1089 // 2. If IsCallable(executor) is false, throw a TypeError exception. |
1042 Bind(&if_notcallable); | 1090 Bind(&if_notcallable); |
1043 { | 1091 { |
1044 Node* const message_id = | 1092 Node* const message_id = |
1045 SmiConstant(MessageTemplate::kResolverNotAFunction); | 1093 SmiConstant(MessageTemplate::kResolverNotAFunction); |
1046 CallRuntime(Runtime::kThrowTypeError, context, message_id, executor); | 1094 CallRuntime(Runtime::kThrowTypeError, context, message_id, executor); |
1047 Return(UndefinedConstant()); // Never reached. | 1095 Return(UndefinedConstant()); // Never reached. |
1048 } | 1096 } |
| 1097 |
| 1098 // Silently fail if the stack looks fishy. |
| 1099 Bind(&if_noaccess); |
| 1100 { |
| 1101 Node* const counter_id = |
| 1102 SmiConstant(v8::Isolate::kPromiseConstructorReturnedUndefined); |
| 1103 CallRuntime(Runtime::kIncrementUseCounter, context, counter_id); |
| 1104 Return(UndefinedConstant()); |
| 1105 } |
1049 } | 1106 } |
1050 | 1107 |
1051 TF_BUILTIN(PromiseInternalConstructor, PromiseBuiltinsAssembler) { | 1108 TF_BUILTIN(PromiseInternalConstructor, PromiseBuiltinsAssembler) { |
1052 Node* const parent = Parameter(1); | 1109 Node* const parent = Parameter(1); |
1053 Node* const context = Parameter(4); | 1110 Node* const context = Parameter(4); |
1054 Return(AllocateAndInitJSPromise(context, parent)); | 1111 Return(AllocateAndInitJSPromise(context, parent)); |
1055 } | 1112 } |
1056 | 1113 |
1057 TF_BUILTIN(IsPromise, PromiseBuiltinsAssembler) { | 1114 TF_BUILTIN(IsPromise, PromiseBuiltinsAssembler) { |
1058 Node* const maybe_promise = Parameter(1); | 1115 Node* const maybe_promise = Parameter(1); |
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1449 | 1506 |
1450 // 5. Return promiseCapability.[[Promise]]. | 1507 // 5. Return promiseCapability.[[Promise]]. |
1451 Node* const promise = | 1508 Node* const promise = |
1452 LoadObjectField(capability, JSPromiseCapability::kPromiseOffset); | 1509 LoadObjectField(capability, JSPromiseCapability::kPromiseOffset); |
1453 Return(promise); | 1510 Return(promise); |
1454 } | 1511 } |
1455 } | 1512 } |
1456 | 1513 |
1457 } // namespace internal | 1514 } // namespace internal |
1458 } // namespace v8 | 1515 } // namespace v8 |
OLD | NEW |