Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(138)

Side by Side Diff: src/builtins/builtins-promise.cc

Issue 2567333002: [promises] port NewPromiseCapability to TF (Closed)
Patch Set: Make gcmole happy Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/builtins/builtins-promise.h ('k') | src/code-stub-assembler.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 13 matching lines...) Expand all
24 24
25 Label out(this); 25 Label out(this);
26 GotoUnless(IsPromiseHookEnabled(), &out); 26 GotoUnless(IsPromiseHookEnabled(), &out);
27 CallRuntime(Runtime::kPromiseHookInit, context, instance, parent); 27 CallRuntime(Runtime::kPromiseHookInit, context, instance, parent);
28 Goto(&out); 28 Goto(&out);
29 29
30 Bind(&out); 30 Bind(&out);
31 return instance; 31 return instance;
32 } 32 }
33 33
34 Node* PromiseBuiltinsAssembler::CreatePromiseResolvingFunctionsContext( 34 std::pair<Node*, Node*>
35 PromiseBuiltinsAssembler::CreatePromiseResolvingFunctions(
35 Node* promise, Node* debug_event, Node* native_context) { 36 Node* promise, Node* debug_event, Node* native_context) {
36 Node* const context = 37 Node* const promise_context = CreatePromiseResolvingFunctionsContext(
37 Allocate(FixedArray::SizeFor(PromiseUtils::kPromiseContextLength)); 38 promise, debug_event, native_context);
39 Node* const map = LoadContextElement(
40 native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
41 Node* const resolve_info =
42 LoadContextElement(native_context, Context::PROMISE_RESOLVE_SHARED_FUN);
43 Node* const resolve =
44 AllocateFunctionWithMapAndContext(map, resolve_info, promise_context);
45 Node* const reject_info =
46 LoadContextElement(native_context, Context::PROMISE_REJECT_SHARED_FUN);
47 Node* const reject =
48 AllocateFunctionWithMapAndContext(map, reject_info, promise_context);
49 return std::make_pair(resolve, reject);
50 }
51
52 Node* PromiseBuiltinsAssembler::NewPromiseCapability(Node* context,
53 Node* constructor,
54 Node* debug_event) {
55 if (debug_event == nullptr) {
56 debug_event = TrueConstant();
57 }
58
59 Node* native_context = LoadNativeContext(context);
60
61 Node* map = LoadRoot(Heap::kJSPromiseCapabilityMapRootIndex);
62 Node* capability = AllocateJSObjectFromMap(map);
63
64 StoreObjectFieldNoWriteBarrier(
65 capability, JSPromiseCapability::kPromiseOffset, UndefinedConstant());
66 StoreObjectFieldNoWriteBarrier(
67 capability, JSPromiseCapability::kResolveOffset, UndefinedConstant());
68 StoreObjectFieldNoWriteBarrier(capability, JSPromiseCapability::kRejectOffset,
69 UndefinedConstant());
70
71 Variable var_result(this, MachineRepresentation::kTagged);
72 var_result.Bind(capability);
73
74 Label if_builtin_promise(this), if_custom_promise(this, Label::kDeferred),
75 out(this);
76 Branch(WordEqual(constructor,
77 LoadContextElement(native_context,
78 Context::PROMISE_FUNCTION_INDEX)),
79 &if_builtin_promise, &if_custom_promise);
80
81 Bind(&if_builtin_promise);
82 {
83 Node* promise = AllocateJSPromise(context);
84 PromiseInit(promise);
85 StoreObjectFieldNoWriteBarrier(
86 capability, JSPromiseCapability::kPromiseOffset, promise);
87
88 Node* resolve = nullptr;
89 Node* reject = nullptr;
90
91 std::tie(resolve, reject) =
92 CreatePromiseResolvingFunctions(promise, debug_event, native_context);
93 StoreObjectField(capability, JSPromiseCapability::kResolveOffset, resolve);
94 StoreObjectField(capability, JSPromiseCapability::kRejectOffset, reject);
95
96 GotoUnless(IsPromiseHookEnabled(), &out);
97 CallRuntime(Runtime::kPromiseHookInit, context, promise,
98 UndefinedConstant());
99 Goto(&out);
100 }
101
102 Bind(&if_custom_promise);
103 {
104 Label if_notcallable(this, Label::kDeferred);
105 Node* executor_context =
106 CreatePromiseGetCapabilitiesExecutorContext(capability, native_context);
107 Node* executor_info = LoadContextElement(
108 native_context, Context::PROMISE_GET_CAPABILITIES_EXECUTOR_SHARED_FUN);
109 Node* function_map = LoadContextElement(
110 native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
111 Node* executor = AllocateFunctionWithMapAndContext(
112 function_map, executor_info, executor_context);
113
114 Node* promise = ConstructJS(CodeFactory::Construct(isolate()), context,
115 constructor, executor);
116
117 Node* resolve =
118 LoadObjectField(capability, JSPromiseCapability::kResolveOffset);
119 GotoIf(TaggedIsSmi(resolve), &if_notcallable);
120 GotoUnless(IsCallableMap(LoadMap(resolve)), &if_notcallable);
121
122 Node* reject =
123 LoadObjectField(capability, JSPromiseCapability::kRejectOffset);
124 GotoIf(TaggedIsSmi(reject), &if_notcallable);
125 GotoUnless(IsCallableMap(LoadMap(reject)), &if_notcallable);
126
127 StoreObjectField(capability, JSPromiseCapability::kPromiseOffset, promise);
128
129 Goto(&out);
130
131 Bind(&if_notcallable);
132 Node* message = SmiConstant(MessageTemplate::kPromiseNonCallable);
133 StoreObjectField(capability, JSPromiseCapability::kPromiseOffset,
134 UndefinedConstant());
135 StoreObjectField(capability, JSPromiseCapability::kResolveOffset,
136 UndefinedConstant());
137 StoreObjectField(capability, JSPromiseCapability::kRejectOffset,
138 UndefinedConstant());
139 CallRuntime(Runtime::kThrowTypeError, context, message);
140 var_result.Bind(UndefinedConstant());
141 Goto(&out);
142 }
143
144 Bind(&out);
145 return var_result.value();
146 }
147
148 Node* PromiseBuiltinsAssembler::CreatePromiseContext(Node* native_context,
149 int slots) {
150 DCHECK_GE(slots, Context::MIN_CONTEXT_SLOTS);
151
152 Node* const context = Allocate(FixedArray::SizeFor(slots));
38 StoreMapNoWriteBarrier(context, Heap::kFunctionContextMapRootIndex); 153 StoreMapNoWriteBarrier(context, Heap::kFunctionContextMapRootIndex);
39 StoreObjectFieldNoWriteBarrier( 154 StoreObjectFieldNoWriteBarrier(context, FixedArray::kLengthOffset,
40 context, FixedArray::kLengthOffset, 155 SmiConstant(slots));
41 SmiConstant(PromiseUtils::kPromiseContextLength));
42 156
43 Node* const empty_fn = 157 Node* const empty_fn =
44 LoadContextElement(native_context, Context::CLOSURE_INDEX); 158 LoadContextElement(native_context, Context::CLOSURE_INDEX);
45 StoreContextElementNoWriteBarrier(context, Context::CLOSURE_INDEX, empty_fn); 159 StoreContextElementNoWriteBarrier(context, Context::CLOSURE_INDEX, empty_fn);
46 StoreContextElementNoWriteBarrier(context, Context::PREVIOUS_INDEX, 160 StoreContextElementNoWriteBarrier(context, Context::PREVIOUS_INDEX,
47 UndefinedConstant()); 161 UndefinedConstant());
48 StoreContextElementNoWriteBarrier(context, Context::EXTENSION_INDEX, 162 StoreContextElementNoWriteBarrier(context, Context::EXTENSION_INDEX,
49 TheHoleConstant()); 163 TheHoleConstant());
50 StoreContextElementNoWriteBarrier(context, Context::NATIVE_CONTEXT_INDEX, 164 StoreContextElementNoWriteBarrier(context, Context::NATIVE_CONTEXT_INDEX,
51 native_context); 165 native_context);
166 return context;
167 }
168
169 Node* PromiseBuiltinsAssembler::CreatePromiseResolvingFunctionsContext(
170 Node* promise, Node* debug_event, Node* native_context) {
171 Node* const context =
172 CreatePromiseContext(native_context, PromiseUtils::kPromiseContextLength);
52 StoreContextElementNoWriteBarrier(context, PromiseUtils::kAlreadyVisitedSlot, 173 StoreContextElementNoWriteBarrier(context, PromiseUtils::kAlreadyVisitedSlot,
53 SmiConstant(0)); 174 SmiConstant(0));
54 StoreContextElementNoWriteBarrier(context, PromiseUtils::kPromiseSlot, 175 StoreContextElementNoWriteBarrier(context, PromiseUtils::kPromiseSlot,
55 promise); 176 promise);
56 StoreContextElementNoWriteBarrier(context, PromiseUtils::kDebugEventSlot, 177 StoreContextElementNoWriteBarrier(context, PromiseUtils::kDebugEventSlot,
57 debug_event); 178 debug_event);
58 return context; 179 return context;
59 } 180 }
60 181
61 std::pair<Node*, Node*> 182 Node* PromiseBuiltinsAssembler::CreatePromiseGetCapabilitiesExecutorContext(
62 PromiseBuiltinsAssembler::CreatePromiseResolvingFunctions( 183 Node* promise_capability, Node* native_context) {
63 Node* promise, Node* debug_event, Node* native_context) { 184 int kContextLength = GetPromiseCapabilityExecutor::kContextLength;
64 Node* const promise_context = CreatePromiseResolvingFunctionsContext( 185 Node* context = CreatePromiseContext(native_context, kContextLength);
65 promise, debug_event, native_context); 186 StoreContextElementNoWriteBarrier(
66 Node* const map = LoadContextElement( 187 context, GetPromiseCapabilityExecutor::kCapabilitySlot,
67 native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX); 188 promise_capability);
68 Node* const resolve_info = 189 return context;
69 LoadContextElement(native_context, Context::PROMISE_RESOLVE_SHARED_FUN);
70 Node* const resolve =
71 AllocateFunctionWithMapAndContext(map, resolve_info, promise_context);
72 Node* const reject_info =
73 LoadContextElement(native_context, Context::PROMISE_REJECT_SHARED_FUN);
74 Node* const reject =
75 AllocateFunctionWithMapAndContext(map, reject_info, promise_context);
76
77 return std::make_pair(resolve, reject);
78 } 190 }
79 191
80 Node* PromiseBuiltinsAssembler::ThrowIfNotJSReceiver( 192 Node* PromiseBuiltinsAssembler::ThrowIfNotJSReceiver(
81 Node* context, Node* value, MessageTemplate::Template msg_template) { 193 Node* context, Node* value, MessageTemplate::Template msg_template) {
82 Label out(this), throw_exception(this, Label::kDeferred); 194 Label out(this), throw_exception(this, Label::kDeferred);
83 Variable var_value_map(this, MachineRepresentation::kTagged); 195 Variable var_value_map(this, MachineRepresentation::kTagged);
84 196
85 GotoIf(TaggedIsSmi(value), &throw_exception); 197 GotoIf(TaggedIsSmi(value), &throw_exception);
86 198
87 // Load the instance type of the {value}. 199 // Load the instance type of the {value}.
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
227 { 339 {
228 Node* const deferred_promise = AllocateAndInitPromise(context, promise); 340 Node* const deferred_promise = AllocateAndInitPromise(context, promise);
229 var_deferred_promise.Bind(deferred_promise); 341 var_deferred_promise.Bind(deferred_promise);
230 var_deferred_on_resolve.Bind(UndefinedConstant()); 342 var_deferred_on_resolve.Bind(UndefinedConstant());
231 var_deferred_on_reject.Bind(UndefinedConstant()); 343 var_deferred_on_reject.Bind(UndefinedConstant());
232 Goto(&perform_promise_then); 344 Goto(&perform_promise_then);
233 } 345 }
234 346
235 Bind(&promise_capability); 347 Bind(&promise_capability);
236 { 348 {
237 // TODO(gsathya): Move this to TF. 349 Node* const capability = NewPromiseCapability(context, constructor);
238 Node* const new_promise_capability = LoadContextElement( 350 var_deferred_promise.Bind(
239 native_context, Context::NEW_PROMISE_CAPABILITY_INDEX); 351 LoadObjectField(capability, JSPromiseCapability::kPromiseOffset));
240 Node* const deferred = 352 var_deferred_on_resolve.Bind(
241 CallJS(call_callable, context, new_promise_capability, 353 LoadObjectField(capability, JSPromiseCapability::kResolveOffset));
242 UndefinedConstant(), constructor); 354 var_deferred_on_reject.Bind(
243 Callable getproperty_callable = CodeFactory::GetProperty(isolate); 355 LoadObjectField(capability, JSPromiseCapability::kRejectOffset));
244 Node* key = HeapConstant(isolate->factory()->promise_string());
245 Node* const deferred_promise =
246 CallStub(getproperty_callable, context, deferred, key);
247 var_deferred_promise.Bind(deferred_promise);
248
249 key = HeapConstant(isolate->factory()->resolve_string());
250 Node* const deferred_on_resolve =
251 CallStub(getproperty_callable, context, deferred, key);
252 var_deferred_on_resolve.Bind(deferred_on_resolve);
253
254 key = HeapConstant(isolate->factory()->reject_string());
255 Node* const deferred_on_reject =
256 CallStub(getproperty_callable, context, deferred, key);
257 var_deferred_on_reject.Bind(deferred_on_reject);
258
259 Goto(&perform_promise_then); 356 Goto(&perform_promise_then);
260 } 357 }
261 358
262 // 5. Return PerformPromiseThen(promise, onFulfilled, onRejected, 359 // 5. Return PerformPromiseThen(promise, onFulfilled, onRejected,
263 // resultCapability). 360 // resultCapability).
264 Bind(&perform_promise_then); 361 Bind(&perform_promise_then);
265 Node* const result = InternalPerformPromiseThen( 362 Node* const result = InternalPerformPromiseThen(
266 context, promise, on_resolve, on_reject, var_deferred_promise.value(), 363 context, promise, on_resolve, on_reject, var_deferred_promise.value(),
267 var_deferred_on_resolve.value(), var_deferred_on_reject.value()); 364 var_deferred_on_resolve.value(), var_deferred_on_reject.value());
268 return result; 365 return result;
(...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after
664 handle(PromiseUtils::GetDebugEvent(context), isolate); 761 handle(PromiseUtils::GetDebugEvent(context), isolate);
665 MaybeHandle<Object> maybe_result; 762 MaybeHandle<Object> maybe_result;
666 Handle<Object> argv[] = {promise, value, debug_event}; 763 Handle<Object> argv[] = {promise, value, debug_event};
667 RETURN_FAILURE_ON_EXCEPTION( 764 RETURN_FAILURE_ON_EXCEPTION(
668 isolate, Execution::Call(isolate, isolate->promise_internal_reject(), 765 isolate, Execution::Call(isolate, isolate->promise_internal_reject(),
669 isolate->factory()->undefined_value(), 766 isolate->factory()->undefined_value(),
670 arraysize(argv), argv)); 767 arraysize(argv), argv));
671 return isolate->heap()->undefined_value(); 768 return isolate->heap()->undefined_value();
672 } 769 }
673 770
674 // ES#sec-createresolvingfunctions
675 // CreateResolvingFunctions ( promise )
676 TF_BUILTIN(CreateResolvingFunctions, PromiseBuiltinsAssembler) {
677 Node* const promise = Parameter(1);
678 Node* const debug_event = Parameter(2);
679 Node* const context = Parameter(5);
680 Node* const native_context = LoadNativeContext(context);
681
682 Node* resolve = nullptr;
683 Node* reject = nullptr;
684
685 std::tie(resolve, reject) =
686 CreatePromiseResolvingFunctions(promise, debug_event, native_context);
687
688 Node* const kSize = IntPtrConstant(2);
689 const ElementsKind kind = FAST_ELEMENTS;
690 const WriteBarrierMode barrier_mode = SKIP_WRITE_BARRIER;
691 const ParameterMode parameter_mode = INTPTR_PARAMETERS;
692 Node* const arr = AllocateFixedArray(kind, kSize, parameter_mode);
693 StoreFixedArrayElement(arr, 0, resolve, barrier_mode);
694 StoreFixedArrayElement(arr, 1, reject, barrier_mode);
695
696 Node* const array_map = LoadJSArrayElementsMap(kind, native_context);
697 Node* const length = SmiTag(kSize);
698 Node* const result = AllocateUninitializedJSArrayWithoutElements(
699 kind, array_map, length, nullptr);
700
701 StoreObjectField(result, JSObject::kElementsOffset, arr);
702 Return(result);
703 }
704
705 TF_BUILTIN(PromiseConstructor, PromiseBuiltinsAssembler) { 771 TF_BUILTIN(PromiseConstructor, PromiseBuiltinsAssembler) {
706 Node* const executor = Parameter(1); 772 Node* const executor = Parameter(1);
707 Node* const new_target = Parameter(2); 773 Node* const new_target = Parameter(2);
708 Node* const context = Parameter(4); 774 Node* const context = Parameter(4);
709 Isolate* isolate = this->isolate(); 775 Isolate* isolate = this->isolate();
710 776
711 Label if_targetisundefined(this, Label::kDeferred); 777 Label if_targetisundefined(this, Label::kDeferred);
712 778
713 GotoIf(IsUndefined(new_target), &if_targetisundefined); 779 GotoIf(IsUndefined(new_target), &if_targetisundefined);
714 780
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after
1062 Callable getproperty_callable = CodeFactory::GetProperty(isolate); 1128 Callable getproperty_callable = CodeFactory::GetProperty(isolate);
1063 Node* const then = 1129 Node* const then =
1064 CallStub(getproperty_callable, context, promise, then_str); 1130 CallStub(getproperty_callable, context, promise, then_str);
1065 Callable call_callable = CodeFactory::Call(isolate); 1131 Callable call_callable = CodeFactory::Call(isolate);
1066 Node* const result = 1132 Node* const result =
1067 CallJS(call_callable, context, then, promise, on_resolve, on_reject); 1133 CallJS(call_callable, context, then, promise, on_resolve, on_reject);
1068 Return(result); 1134 Return(result);
1069 } 1135 }
1070 } 1136 }
1071 1137
1138 TF_BUILTIN(PromiseGetCapabilitiesExecutor, PromiseBuiltinsAssembler) {
1139 Node* const resolve = Parameter(1);
1140 Node* const reject = Parameter(2);
1141 Node* const context = Parameter(5);
1142
1143 Node* const capability = LoadContextElement(
1144 context, GetPromiseCapabilityExecutor::kCapabilitySlot);
1145
1146 Label if_alreadyinvoked(this, Label::kDeferred);
1147 GotoIf(WordNotEqual(
1148 LoadObjectField(capability, JSPromiseCapability::kResolveOffset),
1149 UndefinedConstant()),
1150 &if_alreadyinvoked);
1151 GotoIf(WordNotEqual(
1152 LoadObjectField(capability, JSPromiseCapability::kRejectOffset),
1153 UndefinedConstant()),
1154 &if_alreadyinvoked);
1155
1156 StoreObjectField(capability, JSPromiseCapability::kResolveOffset, resolve);
1157 StoreObjectField(capability, JSPromiseCapability::kRejectOffset, reject);
1158
1159 Return(UndefinedConstant());
1160
1161 Bind(&if_alreadyinvoked);
1162 Node* message = SmiConstant(MessageTemplate::kPromiseExecutorAlreadyInvoked);
1163 Return(CallRuntime(Runtime::kThrowTypeError, context, message));
1164 }
1165
1166 TF_BUILTIN(NewPromiseCapability, PromiseBuiltinsAssembler) {
1167 Node* constructor = Parameter(1);
1168 Node* debug_event = Parameter(2);
1169 Node* context = Parameter(5);
1170
1171 CSA_ASSERT_JS_ARGC_EQ(this, 2);
1172
1173 Return(NewPromiseCapability(context, constructor, debug_event));
1174 }
1175
1072 } // namespace internal 1176 } // namespace internal
1073 } // namespace v8 1177 } // namespace v8
OLDNEW
« no previous file with comments | « src/builtins/builtins-promise.h ('k') | src/code-stub-assembler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698