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-utils.h" | 6 #include "src/builtins/builtins-utils.h" |
7 #include "src/builtins/builtins.h" | 7 #include "src/builtins/builtins.h" |
8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
9 #include "src/code-stub-assembler.h" | 9 #include "src/code-stub-assembler.h" |
10 #include "src/promise-utils.h" | 10 #include "src/promise-utils.h" |
11 | 11 |
12 namespace v8 { | 12 namespace v8 { |
13 namespace internal { | 13 namespace internal { |
14 | 14 |
15 typedef compiler::Node Node; | 15 typedef compiler::Node Node; |
16 typedef CodeStubAssembler::ParameterMode ParameterMode; | 16 typedef CodeStubAssembler::ParameterMode ParameterMode; |
17 typedef compiler::CodeAssemblerState CodeAssemblerState; | 17 typedef compiler::CodeAssemblerState CodeAssemblerState; |
18 | 18 |
19 Node* PromiseBuiltinsAssembler::CreatePromiseResolvingFunctionsContext( | 19 Node* PromiseBuiltinsAssembler::NewPromiseCapability(Node* context, |
20 Node* promise, Node* debug_event, Node* native_context) { | 20 Node* constructor, |
21 Node* const context = | 21 Node* debug_event) { |
22 Allocate(FixedArray::SizeFor(PromiseUtils::kPromiseContextLength)); | 22 if (debug_event == nullptr) { |
23 StoreMapNoWriteBarrier(context, Heap::kFunctionContextMapRootIndex); | 23 debug_event = TrueConstant(); |
24 } | |
25 | |
26 Node* native_context = LoadNativeContext(context); | |
27 | |
28 Node* map = LoadRoot(Heap::kJSPromiseCapabilityMapRootIndex); | |
29 Node* capability = AllocateJSObjectFromMap(map); | |
30 | |
24 StoreObjectFieldNoWriteBarrier( | 31 StoreObjectFieldNoWriteBarrier( |
25 context, FixedArray::kLengthOffset, | 32 capability, JSPromiseCapability::kPromiseOffset, UndefinedConstant()); |
26 SmiConstant(PromiseUtils::kPromiseContextLength)); | 33 StoreObjectFieldNoWriteBarrier( |
34 capability, JSPromiseCapability::kResolveOffset, UndefinedConstant()); | |
35 StoreObjectFieldNoWriteBarrier(capability, JSPromiseCapability::kRejectOffset, | |
36 UndefinedConstant()); | |
27 | 37 |
28 Node* const empty_fn = | 38 Variable var_result(this, MachineRepresentation::kTagged); |
29 LoadContextElement(native_context, Context::CLOSURE_INDEX); | 39 var_result.Bind(capability); |
30 StoreContextElementNoWriteBarrier(context, Context::CLOSURE_INDEX, empty_fn); | 40 |
41 Label if_builtin_promise(this), if_custom_promise(this), out(this); | |
gsathya
2016/12/29 21:48:47
if_custom_promise can be deferred
| |
42 Branch(WordEqual(constructor, | |
43 LoadContextElement(native_context, | |
44 Context::PROMISE_FUNCTION_INDEX)), | |
45 &if_builtin_promise, &if_custom_promise); | |
46 | |
47 Bind(&if_builtin_promise); | |
48 { | |
49 Node* promise = AllocateJSPromise(context); | |
50 PromiseInit(promise); | |
51 StoreObjectFieldNoWriteBarrier( | |
52 capability, JSPromiseCapability::kPromiseOffset, promise); | |
53 | |
54 Node* resolve = nullptr; | |
55 Node* reject = nullptr; | |
56 | |
57 std::tie(resolve, reject) = | |
58 CreatePromiseResolvingFunctions(promise, debug_event, native_context); | |
59 StoreObjectField(capability, JSPromiseCapability::kResolveOffset, resolve); | |
60 StoreObjectField(capability, JSPromiseCapability::kRejectOffset, reject); | |
61 | |
62 GotoUnless(IsPromiseHookEnabled(), &out); | |
63 CallRuntime(Runtime::kPromiseHookInit, context, promise, | |
64 UndefinedConstant()); | |
65 Goto(&out); | |
66 } | |
67 | |
68 Bind(&if_custom_promise); | |
69 { | |
70 Label if_notcallable(this, Label::kDeferred); | |
71 Node* executor_context = | |
72 CreatePromiseGetCapabilitiesExecutorContext(capability, native_context); | |
73 Node* executor_info = LoadContextElement( | |
74 native_context, Context::PROMISE_GET_CAPABILITIES_EXECUTOR_SHARED_FUN); | |
75 Node* function_map = LoadContextElement( | |
76 native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX); | |
77 Node* executor = AllocateFunctionWithMapAndContext( | |
78 function_map, executor_info, executor_context); | |
79 | |
80 Node* promise = ConstructJS(CodeFactory::Construct(isolate()), context, | |
81 constructor, executor); | |
82 | |
83 Node* resolve = | |
84 LoadObjectField(capability, JSPromiseCapability::kResolveOffset); | |
85 GotoIf(TaggedIsSmi(resolve), &if_notcallable); | |
86 GotoUnless(IsCallableMap(LoadMap(resolve)), &if_notcallable); | |
87 | |
88 Node* reject = | |
89 LoadObjectField(capability, JSPromiseCapability::kRejectOffset); | |
90 GotoIf(TaggedIsSmi(reject), &if_notcallable); | |
91 GotoUnless(IsCallableMap(LoadMap(reject)), &if_notcallable); | |
92 | |
93 StoreObjectField(capability, JSPromiseCapability::kPromiseOffset, promise); | |
94 | |
95 Goto(&out); | |
96 | |
97 Bind(&if_notcallable); | |
98 Node* message = SmiConstant(MessageTemplate::kPromiseNonCallable); | |
99 StoreObjectField(capability, JSPromiseCapability::kPromiseOffset, | |
100 UndefinedConstant()); | |
101 StoreObjectField(capability, JSPromiseCapability::kResolveOffset, | |
102 UndefinedConstant()); | |
103 StoreObjectField(capability, JSPromiseCapability::kRejectOffset, | |
104 UndefinedConstant()); | |
105 CallRuntime(Runtime::kThrowTypeError, context, message); | |
106 var_result.Bind(UndefinedConstant()); | |
107 Goto(&out); | |
108 } | |
109 | |
110 Bind(&out); | |
111 return var_result.value(); | |
112 } | |
113 | |
114 Node* PromiseBuiltinsAssembler::NewInternalPromiseCapability(Node* context, | |
115 Node* parent) { | |
116 Node* promise = AllocateJSPromise(context); | |
117 PromiseInit(promise); | |
118 | |
119 Label out(this); | |
120 | |
121 Node* map = LoadRoot(Heap::kJSPromiseCapabilityMapRootIndex); | |
122 Node* capability = AllocateJSObjectFromMap(map); | |
123 StoreObjectFieldNoWriteBarrier(capability, | |
124 JSPromiseCapability::kPromiseOffset, promise); | |
125 StoreObjectFieldNoWriteBarrier( | |
126 capability, JSPromiseCapability::kResolveOffset, UndefinedConstant()); | |
127 StoreObjectFieldNoWriteBarrier(capability, JSPromiseCapability::kRejectOffset, | |
128 UndefinedConstant()); | |
129 | |
130 GotoUnless(IsPromiseHookEnabled(), &out); | |
131 CallRuntime(Runtime::kPromiseHookInit, context, promise, parent); | |
132 Goto(&out); | |
133 | |
134 Bind(&out); | |
135 return capability; | |
136 } | |
137 | |
138 Node* PromiseBuiltinsAssembler::CreatePromiseContext(Node* native_context, | |
139 int slots) { | |
140 DCHECK_GE(slots, Context::MIN_CONTEXT_SLOTS); | |
141 Node* script = LoadContextElement(native_context, Context::CLOSURE_INDEX); | |
142 Node* map = HeapConstant(isolate()->factory()->function_context_map()); | |
143 Node* context = Allocate(FixedArray::SizeFor(slots)); | |
144 StoreMapNoWriteBarrier(context, map); | |
145 StoreObjectFieldNoWriteBarrier(context, FixedArray::kLengthOffset, | |
146 SmiConstant(slots)); | |
147 StoreContextElementNoWriteBarrier(context, Context::CLOSURE_INDEX, script); | |
31 StoreContextElementNoWriteBarrier(context, Context::PREVIOUS_INDEX, | 148 StoreContextElementNoWriteBarrier(context, Context::PREVIOUS_INDEX, |
32 UndefinedConstant()); | 149 UndefinedConstant()); |
33 StoreContextElementNoWriteBarrier(context, Context::EXTENSION_INDEX, | 150 StoreContextElementNoWriteBarrier(context, Context::EXTENSION_INDEX, |
34 TheHoleConstant()); | 151 TheHoleConstant()); |
35 StoreContextElementNoWriteBarrier(context, Context::NATIVE_CONTEXT_INDEX, | 152 StoreContextElementNoWriteBarrier(context, Context::NATIVE_CONTEXT_INDEX, |
36 native_context); | 153 native_context); |
154 return context; | |
155 } | |
156 | |
157 Node* PromiseBuiltinsAssembler::CreatePromiseResolvingFunctionsContext( | |
158 Node* promise, Node* debug_event, Node* native_context) { | |
159 Node* const context = | |
160 CreatePromiseContext(native_context, PromiseUtils::kPromiseContextLength); | |
37 StoreContextElementNoWriteBarrier(context, PromiseUtils::kAlreadyVisitedSlot, | 161 StoreContextElementNoWriteBarrier(context, PromiseUtils::kAlreadyVisitedSlot, |
38 SmiConstant(0)); | 162 SmiConstant(0)); |
39 StoreContextElementNoWriteBarrier(context, PromiseUtils::kPromiseSlot, | 163 StoreContextElementNoWriteBarrier(context, PromiseUtils::kPromiseSlot, |
40 promise); | 164 promise); |
41 StoreContextElementNoWriteBarrier(context, PromiseUtils::kDebugEventSlot, | 165 StoreContextElementNoWriteBarrier(context, PromiseUtils::kDebugEventSlot, |
42 debug_event); | 166 debug_event); |
43 return context; | 167 return context; |
44 } | 168 } |
45 | 169 |
170 Node* PromiseBuiltinsAssembler::CreatePromiseGetCapabilitiesExecutorContext( | |
171 Node* promise_capability, Node* native_context) { | |
172 int kSize = GetPromiseCapabilityExecutor::kContextLength; | |
173 Node* context = CreatePromiseContext(native_context, kSize); | |
174 StoreContextElementNoWriteBarrier( | |
175 context, GetPromiseCapabilityExecutor::kCapabilitySlot, | |
176 promise_capability); | |
177 return context; | |
178 } | |
179 | |
46 std::pair<Node*, Node*> | 180 std::pair<Node*, Node*> |
47 PromiseBuiltinsAssembler::CreatePromiseResolvingFunctions( | 181 PromiseBuiltinsAssembler::CreatePromiseResolvingFunctions( |
48 Node* promise, Node* debug_event, Node* native_context) { | 182 Node* promise, Node* debug_event, Node* native_context) { |
49 Node* const promise_context = CreatePromiseResolvingFunctionsContext( | 183 Node* const promise_context = CreatePromiseResolvingFunctionsContext( |
50 promise, debug_event, native_context); | 184 promise, debug_event, native_context); |
51 Node* const map = LoadContextElement( | 185 Node* const map = LoadContextElement( |
52 native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX); | 186 native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX); |
53 Node* const resolve_info = | 187 Node* const resolve_info = |
54 LoadContextElement(native_context, Context::PROMISE_RESOLVE_SHARED_FUN); | 188 LoadContextElement(native_context, Context::PROMISE_RESOLVE_SHARED_FUN); |
55 Node* const resolve = | 189 Node* const resolve = |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
199 | 333 |
200 // 4. Let resultCapability be ? NewPromiseCapability(C). | 334 // 4. Let resultCapability be ? NewPromiseCapability(C). |
201 Callable call_callable = CodeFactory::Call(isolate); | 335 Callable call_callable = CodeFactory::Call(isolate); |
202 Label fast_promise_capability(this), promise_capability(this), | 336 Label fast_promise_capability(this), promise_capability(this), |
203 perform_promise_then(this); | 337 perform_promise_then(this); |
204 Variable var_deferred(this, MachineRepresentation::kTagged); | 338 Variable var_deferred(this, MachineRepresentation::kTagged); |
205 | 339 |
206 Branch(WordEqual(promise_fun, constructor), &fast_promise_capability, | 340 Branch(WordEqual(promise_fun, constructor), &fast_promise_capability, |
207 &promise_capability); | 341 &promise_capability); |
208 | 342 |
209 // TODO(gsathya): Remove deferred object and move | 343 // TODO(gsathya): Remove deferred object. |
210 // NewPromiseCapabability functions to TF. | |
211 Bind(&fast_promise_capability); | 344 Bind(&fast_promise_capability); |
212 { | 345 { |
213 // TODO(gsathya): Move this to TF. | 346 Node* const capability = NewInternalPromiseCapability(context, promise); |
214 Node* const promise_internal_capability = LoadContextElement( | |
215 native_context, Context::INTERNAL_PROMISE_CAPABILITY_INDEX); | |
216 Node* const capability = | |
217 CallJS(call_callable, context, promise_internal_capability, | |
218 UndefinedConstant(), promise); | |
219 var_deferred.Bind(capability); | 347 var_deferred.Bind(capability); |
220 Goto(&perform_promise_then); | 348 Goto(&perform_promise_then); |
221 } | 349 } |
222 | 350 |
223 Bind(&promise_capability); | 351 Bind(&promise_capability); |
224 { | 352 { |
225 // TODO(gsathya): Move this to TF. | 353 Node* const capability = NewPromiseCapability(context, constructor); |
226 Node* const new_promise_capability = LoadContextElement( | |
227 native_context, Context::NEW_PROMISE_CAPABILITY_INDEX); | |
228 Node* const capability = | |
229 CallJS(call_callable, context, new_promise_capability, | |
230 UndefinedConstant(), constructor); | |
231 var_deferred.Bind(capability); | 354 var_deferred.Bind(capability); |
232 Goto(&perform_promise_then); | 355 Goto(&perform_promise_then); |
233 } | 356 } |
234 | 357 |
235 // 5. Return PerformPromiseThen(promise, onFulfilled, onRejected, | 358 // 5. Return PerformPromiseThen(promise, onFulfilled, onRejected, |
236 // resultCapability). | 359 // resultCapability). |
237 Bind(&perform_promise_then); | 360 Bind(&perform_promise_then); |
238 Node* const result = InternalPerformPromiseThen( | 361 Node* const result = InternalPerformPromiseThen( |
239 context, promise, on_resolve, on_reject, var_deferred.value()); | 362 context, promise, on_resolve, on_reject, var_deferred.value()); |
240 return result; | 363 return result; |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
390 | 513 |
391 Goto(&out); | 514 Goto(&out); |
392 } | 515 } |
393 } | 516 } |
394 } | 517 } |
395 } | 518 } |
396 | 519 |
397 Bind(&out); | 520 Bind(&out); |
398 PromiseSetHasHandler(promise); | 521 PromiseSetHasHandler(promise); |
399 | 522 |
400 // TODO(gsathya): This call will be removed once we don't have to | 523 CSA_ASSERT(this, HasInstanceType(deferred, JS_PROMISE_CAPABILITY_TYPE)); |
401 // deal with deferred objects. | 524 Node* then_promise = |
402 Isolate* isolate = this->isolate(); | 525 LoadObjectField(deferred, JSPromiseCapability::kPromiseOffset); |
403 Callable getproperty_callable = CodeFactory::GetProperty(isolate); | 526 return then_promise; |
404 Node* const key = | |
405 HeapConstant(isolate->factory()->NewStringFromAsciiChecked("promise")); | |
406 Node* const result = CallStub(getproperty_callable, context, deferred, key); | |
407 | |
408 return result; | |
409 } | 527 } |
410 | 528 |
411 // Promise fast path implementations rely on unmodified JSPromise instances. | 529 // Promise fast path implementations rely on unmodified JSPromise instances. |
412 // We use a fairly coarse granularity for this and simply check whether both | 530 // We use a fairly coarse granularity for this and simply check whether both |
413 // the promise itself is unmodified (i.e. its map has not changed) and its | 531 // the promise itself is unmodified (i.e. its map has not changed) and its |
414 // prototype is unmodified. | 532 // prototype is unmodified. |
415 // TODO(gsathya): Refactor this out to prevent code dupe with builtins-regexp | 533 // TODO(gsathya): Refactor this out to prevent code dupe with builtins-regexp |
416 void PromiseBuiltinsAssembler::BranchIfFastPath(Node* context, Node* promise, | 534 void PromiseBuiltinsAssembler::BranchIfFastPath(Node* context, Node* promise, |
417 Label* if_isunmodified, | 535 Label* if_isunmodified, |
418 Label* if_ismodified) { | 536 Label* if_ismodified) { |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
611 handle(PromiseUtils::GetDebugEvent(context), isolate); | 729 handle(PromiseUtils::GetDebugEvent(context), isolate); |
612 MaybeHandle<Object> maybe_result; | 730 MaybeHandle<Object> maybe_result; |
613 Handle<Object> argv[] = {promise, value, debug_event}; | 731 Handle<Object> argv[] = {promise, value, debug_event}; |
614 RETURN_FAILURE_ON_EXCEPTION( | 732 RETURN_FAILURE_ON_EXCEPTION( |
615 isolate, Execution::Call(isolate, isolate->promise_internal_reject(), | 733 isolate, Execution::Call(isolate, isolate->promise_internal_reject(), |
616 isolate->factory()->undefined_value(), | 734 isolate->factory()->undefined_value(), |
617 arraysize(argv), argv)); | 735 arraysize(argv), argv)); |
618 return isolate->heap()->undefined_value(); | 736 return isolate->heap()->undefined_value(); |
619 } | 737 } |
620 | 738 |
621 // ES#sec-createresolvingfunctions | |
622 // CreateResolvingFunctions ( promise ) | |
623 TF_BUILTIN(CreateResolvingFunctions, PromiseBuiltinsAssembler) { | |
624 Node* const promise = Parameter(1); | |
625 Node* const debug_event = Parameter(2); | |
626 Node* const context = Parameter(5); | |
627 Node* const native_context = LoadNativeContext(context); | |
628 | |
629 Node* resolve = nullptr; | |
630 Node* reject = nullptr; | |
631 | |
632 std::tie(resolve, reject) = | |
633 CreatePromiseResolvingFunctions(promise, debug_event, native_context); | |
634 | |
635 Node* const kSize = IntPtrConstant(2); | |
636 const ElementsKind kind = FAST_ELEMENTS; | |
637 const WriteBarrierMode barrier_mode = SKIP_WRITE_BARRIER; | |
638 const ParameterMode parameter_mode = INTPTR_PARAMETERS; | |
639 Node* const arr = AllocateFixedArray(kind, kSize, parameter_mode); | |
640 StoreFixedArrayElement(arr, 0, resolve, barrier_mode); | |
641 StoreFixedArrayElement(arr, 1, reject, barrier_mode); | |
642 | |
643 Node* const array_map = LoadJSArrayElementsMap(kind, native_context); | |
644 Node* const length = SmiTag(kSize); | |
645 Node* const result = AllocateUninitializedJSArrayWithoutElements( | |
646 kind, array_map, length, nullptr); | |
647 | |
648 StoreObjectField(result, JSObject::kElementsOffset, arr); | |
649 Return(result); | |
650 } | |
651 | |
652 TF_BUILTIN(PromiseConstructor, PromiseBuiltinsAssembler) { | 739 TF_BUILTIN(PromiseConstructor, PromiseBuiltinsAssembler) { |
653 Node* const executor = Parameter(1); | 740 Node* const executor = Parameter(1); |
654 Node* const new_target = Parameter(2); | 741 Node* const new_target = Parameter(2); |
655 Node* const context = Parameter(4); | 742 Node* const context = Parameter(4); |
656 Isolate* isolate = this->isolate(); | 743 Isolate* isolate = this->isolate(); |
657 | 744 |
658 Label if_targetisundefined(this, Label::kDeferred); | 745 Label if_targetisundefined(this, Label::kDeferred); |
659 | 746 |
660 GotoIf(IsUndefined(new_target), &if_targetisundefined); | 747 GotoIf(IsUndefined(new_target), &if_targetisundefined); |
661 | 748 |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
908 | 995 |
909 TF_BUILTIN(PromiseHandle, PromiseBuiltinsAssembler) { | 996 TF_BUILTIN(PromiseHandle, PromiseBuiltinsAssembler) { |
910 Node* const promise = Parameter(1); | 997 Node* const promise = Parameter(1); |
911 Node* const value = Parameter(2); | 998 Node* const value = Parameter(2); |
912 Node* const handler = Parameter(3); | 999 Node* const handler = Parameter(3); |
913 Node* const deferred = Parameter(4); | 1000 Node* const deferred = Parameter(4); |
914 Node* const context = Parameter(7); | 1001 Node* const context = Parameter(7); |
915 Isolate* isolate = this->isolate(); | 1002 Isolate* isolate = this->isolate(); |
916 | 1003 |
917 // Get promise from deferred | 1004 // Get promise from deferred |
918 // TODO(gsathya): Remove this lookup by getting rid of the deferred object. | 1005 CSA_ASSERT(this, HasInstanceType(deferred, JS_PROMISE_CAPABILITY_TYPE)); |
919 Callable getproperty_callable = CodeFactory::GetProperty(isolate); | |
920 Node* const key = HeapConstant(isolate->factory()->promise_string()); | |
921 Node* const deferred_promise = | 1006 Node* const deferred_promise = |
922 CallStub(getproperty_callable, context, deferred, key); | 1007 LoadObjectField(deferred, JSPromiseCapability::kPromiseOffset); |
923 | 1008 |
924 Variable var_reason(this, MachineRepresentation::kTagged); | 1009 Variable var_reason(this, MachineRepresentation::kTagged); |
925 | 1010 |
926 Node* const is_debug_active = IsDebugActive(); | 1011 Node* const is_debug_active = IsDebugActive(); |
927 Label run_handler(this), if_rejectpromise(this), promisehook_before(this), | 1012 Label run_handler(this), if_rejectpromise(this), promisehook_before(this), |
928 promisehook_after(this), debug_pop(this); | 1013 promisehook_after(this), debug_pop(this); |
929 | 1014 |
930 GotoUnless(is_debug_active, &promisehook_before); | 1015 GotoUnless(is_debug_active, &promisehook_before); |
931 CallRuntime(Runtime::kDebugPushPromise, context, deferred_promise); | 1016 CallRuntime(Runtime::kDebugPushPromise, context, deferred_promise); |
932 Goto(&promisehook_before); | 1017 Goto(&promisehook_before); |
933 | 1018 |
934 Bind(&promisehook_before); | 1019 Bind(&promisehook_before); |
935 { | 1020 { |
936 GotoUnless(IsPromiseHookEnabled(), &run_handler); | 1021 GotoUnless(IsPromiseHookEnabled(), &run_handler); |
937 CallRuntime(Runtime::kPromiseHookBefore, context, promise); | 1022 CallRuntime(Runtime::kPromiseHookBefore, context, promise); |
938 Goto(&run_handler); | 1023 Goto(&run_handler); |
939 } | 1024 } |
940 | 1025 |
941 Bind(&run_handler); | 1026 Bind(&run_handler); |
942 { | 1027 { |
943 Callable call_callable = CodeFactory::Call(isolate); | 1028 Callable call_callable = CodeFactory::Call(isolate); |
944 | 1029 |
945 Node* const result = | 1030 Node* const result = |
946 CallJS(call_callable, context, handler, UndefinedConstant(), value); | 1031 CallJS(call_callable, context, handler, UndefinedConstant(), value); |
947 | 1032 |
948 GotoIfException(result, &if_rejectpromise, &var_reason); | 1033 GotoIfException(result, &if_rejectpromise, &var_reason); |
949 | 1034 |
950 // TODO(gsathya): Remove this lookup by getting rid of the deferred object. | |
951 Node* const key = HeapConstant(isolate->factory()->resolve_string()); | |
952 Node* const on_resolve = | 1035 Node* const on_resolve = |
953 CallStub(getproperty_callable, context, deferred, key); | 1036 LoadObjectField(deferred, JSPromiseCapability::kResolveOffset); |
954 | 1037 |
955 Label if_internalhandler(this), if_customhandler(this, Label::kDeferred); | 1038 Label if_internalhandler(this), if_customhandler(this, Label::kDeferred); |
956 Branch(IsUndefined(on_resolve), &if_internalhandler, &if_customhandler); | 1039 Branch(IsUndefined(on_resolve), &if_internalhandler, &if_customhandler); |
957 | 1040 |
958 Bind(&if_internalhandler); | 1041 Bind(&if_internalhandler); |
959 InternalResolvePromise(context, deferred_promise, result); | 1042 InternalResolvePromise(context, deferred_promise, result); |
960 Goto(&promisehook_after); | 1043 Goto(&promisehook_after); |
961 | 1044 |
962 Bind(&if_customhandler); | 1045 Bind(&if_customhandler); |
963 { | 1046 { |
964 Node* const maybe_exception = CallJS(call_callable, context, on_resolve, | 1047 Node* const maybe_exception = CallJS(call_callable, context, on_resolve, |
965 UndefinedConstant(), result); | 1048 UndefinedConstant(), result); |
966 GotoIfException(maybe_exception, &if_rejectpromise, &var_reason); | 1049 GotoIfException(maybe_exception, &if_rejectpromise, &var_reason); |
967 Goto(&promisehook_after); | 1050 Goto(&promisehook_after); |
968 } | 1051 } |
969 } | 1052 } |
970 | 1053 |
971 Bind(&if_rejectpromise); | 1054 Bind(&if_rejectpromise); |
972 { | 1055 { |
973 // TODO(gsathya): Remove this lookup by getting rid of the deferred object. | |
974 Node* const key = HeapConstant(isolate->factory()->reject_string()); | |
975 Node* const on_reject = | 1056 Node* const on_reject = |
976 CallStub(getproperty_callable, context, deferred, key); | 1057 LoadObjectField(deferred, JSPromiseCapability::kRejectOffset); |
977 | 1058 |
978 Callable promise_handle_reject = CodeFactory::PromiseHandleReject(isolate); | 1059 Callable promise_handle_reject = CodeFactory::PromiseHandleReject(isolate); |
979 CallStub(promise_handle_reject, context, deferred_promise, on_reject, | 1060 CallStub(promise_handle_reject, context, deferred_promise, on_reject, |
980 var_reason.value()); | 1061 var_reason.value()); |
981 Goto(&promisehook_after); | 1062 Goto(&promisehook_after); |
982 } | 1063 } |
983 | 1064 |
984 Bind(&promisehook_after); | 1065 Bind(&promisehook_after); |
985 { | 1066 { |
986 GotoUnless(IsPromiseHookEnabled(), &debug_pop); | 1067 GotoUnless(IsPromiseHookEnabled(), &debug_pop); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1027 Callable getproperty_callable = CodeFactory::GetProperty(isolate); | 1108 Callable getproperty_callable = CodeFactory::GetProperty(isolate); |
1028 Node* const then = | 1109 Node* const then = |
1029 CallStub(getproperty_callable, context, promise, then_str); | 1110 CallStub(getproperty_callable, context, promise, then_str); |
1030 Callable call_callable = CodeFactory::Call(isolate); | 1111 Callable call_callable = CodeFactory::Call(isolate); |
1031 Node* const result = | 1112 Node* const result = |
1032 CallJS(call_callable, context, then, promise, on_resolve, on_reject); | 1113 CallJS(call_callable, context, then, promise, on_resolve, on_reject); |
1033 Return(result); | 1114 Return(result); |
1034 } | 1115 } |
1035 } | 1116 } |
1036 | 1117 |
1118 TF_BUILTIN(PromiseGetCapabilitiesExecutor, PromiseBuiltinsAssembler) { | |
1119 Node* const resolve = Parameter(1); | |
1120 Node* const reject = Parameter(2); | |
1121 Node* const context = Parameter(5); | |
1122 | |
1123 Node* const capability = LoadContextElement( | |
1124 context, GetPromiseCapabilityExecutor::kCapabilitySlot); | |
1125 | |
1126 Label if_alreadyinvoked(this, Label::kDeferred); | |
1127 GotoIf(WordNotEqual( | |
1128 LoadObjectField(capability, JSPromiseCapability::kResolveOffset), | |
1129 UndefinedConstant()), | |
1130 &if_alreadyinvoked); | |
1131 GotoIf(WordNotEqual( | |
1132 LoadObjectField(capability, JSPromiseCapability::kRejectOffset), | |
1133 UndefinedConstant()), | |
1134 &if_alreadyinvoked); | |
1135 | |
1136 StoreObjectField(capability, JSPromiseCapability::kResolveOffset, resolve); | |
1137 StoreObjectField(capability, JSPromiseCapability::kRejectOffset, reject); | |
1138 | |
1139 Return(UndefinedConstant()); | |
1140 | |
1141 Bind(&if_alreadyinvoked); | |
1142 Node* message = SmiConstant(MessageTemplate::kPromiseExecutorAlreadyInvoked); | |
1143 Return(CallRuntime(Runtime::kThrowTypeError, context, message)); | |
1144 } | |
1145 | |
1146 TF_BUILTIN(NewPromiseCapability, PromiseBuiltinsAssembler) { | |
1147 Node* constructor = Parameter(1); | |
1148 Node* debug_event = Parameter(2); | |
1149 Node* context = Parameter(5); | |
1150 | |
1151 CSA_ASSERT_JS_ARGC_EQ(this, 2); | |
1152 | |
1153 Return(NewPromiseCapability(context, constructor, debug_event)); | |
1154 } | |
1155 | |
1156 TF_BUILTIN(NewInternalPromiseCapability, PromiseBuiltinsAssembler) { | |
1157 Node* parent = Parameter(1); | |
1158 Node* context = Parameter(4); | |
1159 CSA_ASSERT_JS_ARGC_EQ(this, 1); | |
1160 | |
1161 Return(NewInternalPromiseCapability(context, parent)); | |
1162 } | |
1163 | |
1037 } // namespace internal | 1164 } // namespace internal |
1038 } // namespace v8 | 1165 } // namespace v8 |
OLD | NEW |