5 #include "src/builtins/builtins-async-gen.h" 7 #include "src/builtins/builtins-utils-gen.h" 8 #include "src/heap/factory-inl.h" 9 #include "src/objects/js-promise.h" 10 #include "src/objects/shared-function-info.h" 19 class ValueUnwrapContext {
21 enum Fields { kDoneSlot = Context::MIN_CONTEXT_SLOTS, kLength };
26 Node* AsyncBuiltinsAssembler::AwaitOld(Node* context, Node* generator,
27 Node* value, Node* outer_promise,
28 Node* on_resolve_context_index,
29 Node* on_reject_context_index,
30 Node* is_predicted_as_caught) {
31 Node*
const native_context = LoadNativeContext(context);
33 static const int kWrappedPromiseOffset =
34 FixedArray::SizeFor(Context::MIN_CONTEXT_SLOTS);
35 static const int kResolveClosureOffset =
36 kWrappedPromiseOffset + JSPromise::kSizeWithEmbedderFields;
37 static const int kRejectClosureOffset =
38 kResolveClosureOffset + JSFunction::kSizeWithoutPrototype;
39 static const int kTotalSize =
40 kRejectClosureOffset + JSFunction::kSizeWithoutPrototype;
42 TNode<HeapObject> base = AllocateInNewSpace(kTotalSize);
43 TNode<Context> closure_context = UncheckedCast<Context>(base);
46 StoreMapNoWriteBarrier(closure_context, RootIndex::kAwaitContextMap);
47 StoreObjectFieldNoWriteBarrier(closure_context, Context::kLengthOffset,
48 SmiConstant(Context::MIN_CONTEXT_SLOTS));
49 Node*
const empty_scope_info =
50 LoadContextElement(native_context, Context::SCOPE_INFO_INDEX);
51 StoreContextElementNoWriteBarrier(
52 closure_context, Context::SCOPE_INFO_INDEX, empty_scope_info);
53 StoreContextElementNoWriteBarrier(closure_context, Context::PREVIOUS_INDEX,
55 StoreContextElementNoWriteBarrier(closure_context, Context::EXTENSION_INDEX,
57 StoreContextElementNoWriteBarrier(
58 closure_context, Context::NATIVE_CONTEXT_INDEX, native_context);
62 Node*
const promise_fun =
63 LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
64 CSA_ASSERT(
this, IsFunctionWithPrototypeSlotMap(LoadMap(promise_fun)));
65 Node*
const promise_map =
66 LoadObjectField(promise_fun, JSFunction::kPrototypeOrInitialMapOffset);
69 CSA_ASSERT(
this, WordEqual(LoadMapInstanceSizeInWords(promise_map),
70 IntPtrConstant(JSPromise::kSizeWithEmbedderFields /
72 TNode<HeapObject> wrapped_value = InnerAllocate(base, kWrappedPromiseOffset);
75 StoreMapNoWriteBarrier(wrapped_value, promise_map);
76 StoreObjectFieldRoot(wrapped_value, JSPromise::kPropertiesOrHashOffset,
77 RootIndex::kEmptyFixedArray);
78 StoreObjectFieldRoot(wrapped_value, JSPromise::kElementsOffset,
79 RootIndex::kEmptyFixedArray);
80 PromiseInit(wrapped_value);
84 TNode<HeapObject> on_resolve = InnerAllocate(base, kResolveClosureOffset);
85 InitializeNativeClosure(closure_context, native_context, on_resolve,
86 on_resolve_context_index);
89 TNode<HeapObject> on_reject = InnerAllocate(base, kRejectClosureOffset);
90 InitializeNativeClosure(closure_context, native_context, on_reject,
91 on_reject_context_index);
93 VARIABLE(var_throwaway, MachineRepresentation::kTaggedPointer,
99 Label if_debugging(
this, Label::kDeferred), do_resolve_promise(
this);
100 Branch(IsPromiseHookEnabledOrDebugIsActiveOrHasAsyncEventDelegate(),
101 &if_debugging, &do_resolve_promise);
103 var_throwaway.Bind(CallRuntime(Runtime::kAwaitPromisesInitOld, context, value,
104 wrapped_value, outer_promise, on_reject,
105 is_predicted_as_caught));
106 Goto(&do_resolve_promise);
107 BIND(&do_resolve_promise);
110 CallBuiltin(Builtins::kResolvePromise, context, wrapped_value, value);
112 return CallBuiltin(Builtins::kPerformPromiseThen, context, wrapped_value,
113 on_resolve, on_reject, var_throwaway.value());
116 Node* AsyncBuiltinsAssembler::AwaitOptimized(Node* context, Node* generator,
117 Node* promise, Node* outer_promise,
118 Node* on_resolve_context_index,
119 Node* on_reject_context_index,
120 Node* is_predicted_as_caught) {
121 Node*
const native_context = LoadNativeContext(context);
122 CSA_ASSERT(
this, IsJSPromise(promise));
124 static const int kResolveClosureOffset =
125 FixedArray::SizeFor(Context::MIN_CONTEXT_SLOTS);
126 static const int kRejectClosureOffset =
127 kResolveClosureOffset + JSFunction::kSizeWithoutPrototype;
128 static const int kTotalSize =
129 kRejectClosureOffset + JSFunction::kSizeWithoutPrototype;
135 TNode<HeapObject> base = AllocateInNewSpace(kTotalSize);
136 TNode<Context> closure_context = UncheckedCast<Context>(base);
139 StoreMapNoWriteBarrier(closure_context, RootIndex::kAwaitContextMap);
140 StoreObjectFieldNoWriteBarrier(closure_context, Context::kLengthOffset,
141 SmiConstant(Context::MIN_CONTEXT_SLOTS));
142 Node*
const empty_scope_info =
143 LoadContextElement(native_context, Context::SCOPE_INFO_INDEX);
144 StoreContextElementNoWriteBarrier(
145 closure_context, Context::SCOPE_INFO_INDEX, empty_scope_info);
146 StoreContextElementNoWriteBarrier(closure_context, Context::PREVIOUS_INDEX,
148 StoreContextElementNoWriteBarrier(closure_context, Context::EXTENSION_INDEX,
150 StoreContextElementNoWriteBarrier(
151 closure_context, Context::NATIVE_CONTEXT_INDEX, native_context);
155 TNode<HeapObject> on_resolve = InnerAllocate(base, kResolveClosureOffset);
156 InitializeNativeClosure(closure_context, native_context, on_resolve,
157 on_resolve_context_index);
160 TNode<HeapObject> on_reject = InnerAllocate(base, kRejectClosureOffset);
161 InitializeNativeClosure(closure_context, native_context, on_reject,
162 on_reject_context_index);
164 VARIABLE(var_throwaway, MachineRepresentation::kTaggedPointer,
165 UndefinedConstant());
170 Label if_debugging(
this, Label::kDeferred), do_perform_promise_then(
this);
171 Branch(IsPromiseHookEnabledOrDebugIsActiveOrHasAsyncEventDelegate(),
172 &if_debugging, &do_perform_promise_then);
174 var_throwaway.Bind(CallRuntime(Runtime::kAwaitPromisesInit, context, promise,
175 promise, outer_promise, on_reject,
176 is_predicted_as_caught));
177 Goto(&do_perform_promise_then);
178 BIND(&do_perform_promise_then);
180 return CallBuiltin(Builtins::kPerformPromiseThen, native_context, promise,
181 on_resolve, on_reject, var_throwaway.value());
184 Node* AsyncBuiltinsAssembler::Await(Node* context, Node* generator, Node* value,
186 Node* on_resolve_context_index,
187 Node* on_reject_context_index,
188 Node* is_predicted_as_caught) {
189 VARIABLE(result, MachineRepresentation::kTagged);
190 Label if_old(
this), if_new(
this), done(
this),
191 if_slow_constructor(
this, Label::kDeferred);
193 STATIC_ASSERT(
sizeof(FLAG_harmony_await_optimization) == 1);
194 TNode<Word32T> flag_value = UncheckedCast<Word32T>(Load(
195 MachineType::Uint8(),
197 ExternalReference::address_of_harmony_await_optimization_flag())));
198 GotoIf(Word32Equal(flag_value, Int32Constant(0)), &if_old);
206 GotoIf(TaggedIsSmi(value), &if_old);
207 Node*
const value_map = LoadMap(value);
208 GotoIfNot(IsJSPromiseMap(value_map), &if_old);
213 Node*
const native_context = LoadNativeContext(context);
214 Node*
const promise_prototype =
215 LoadContextElement(native_context, Context::PROMISE_PROTOTYPE_INDEX);
216 GotoIfNot(WordEqual(LoadMapPrototype(value_map), promise_prototype),
217 &if_slow_constructor);
218 Branch(IsPromiseSpeciesProtectorCellInvalid(), &if_slow_constructor, &if_new);
223 BIND(&if_slow_constructor);
225 Node*
const value_constructor =
226 GetProperty(context, value, isolate()->factory()->constructor_string());
227 Node*
const promise_function =
228 LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
229 Branch(WordEqual(value_constructor, promise_function), &if_new, &if_old);
233 result.Bind(AwaitOld(context, generator, value, outer_promise,
234 on_resolve_context_index, on_reject_context_index,
235 is_predicted_as_caught));
239 result.Bind(AwaitOptimized(context, generator, value, outer_promise,
240 on_resolve_context_index, on_reject_context_index,
241 is_predicted_as_caught));
245 return result.value();
248 void AsyncBuiltinsAssembler::InitializeNativeClosure(Node* context,
249 Node* native_context,
251 Node* context_index) {
252 TNode<Map> function_map = CAST(LoadContextElement(
253 native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX));
256 CSA_ASSERT(
this, WordEqual(LoadMapInstanceSizeInWords(function_map),
257 IntPtrConstant(JSFunction::kSizeWithoutPrototype /
259 STATIC_ASSERT(JSFunction::kSizeWithoutPrototype == 7 * kPointerSize);
260 StoreMapNoWriteBarrier(
function, function_map);
261 StoreObjectFieldRoot(
function, JSObject::kPropertiesOrHashOffset,
262 RootIndex::kEmptyFixedArray);
263 StoreObjectFieldRoot(
function, JSObject::kElementsOffset,
264 RootIndex::kEmptyFixedArray);
265 StoreObjectFieldRoot(
function, JSFunction::kFeedbackCellOffset,
266 RootIndex::kManyClosuresCell);
268 TNode<SharedFunctionInfo> shared_info =
269 CAST(LoadContextElement(native_context, context_index));
270 StoreObjectFieldNoWriteBarrier(
271 function, JSFunction::kSharedFunctionInfoOffset, shared_info);
272 StoreObjectFieldNoWriteBarrier(
function, JSFunction::kContextOffset, context);
279 TNode<Smi> builtin_id = LoadObjectField<Smi>(
280 shared_info, SharedFunctionInfo::kFunctionDataOffset);
281 TNode<Code> code = LoadBuiltin(builtin_id);
282 StoreObjectFieldNoWriteBarrier(
function, JSFunction::kCodeOffset, code);
285 Node* AsyncBuiltinsAssembler::CreateUnwrapClosure(Node* native_context,
287 Node*
const map = LoadContextElement(
288 native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
289 Node*
const on_fulfilled_shared = LoadContextElement(
290 native_context, Context::ASYNC_ITERATOR_VALUE_UNWRAP_SHARED_FUN);
292 HasInstanceType(on_fulfilled_shared, SHARED_FUNCTION_INFO_TYPE));
293 Node*
const closure_context =
294 AllocateAsyncIteratorValueUnwrapContext(native_context, done);
295 return AllocateFunctionWithMapAndContext(map, on_fulfilled_shared,
299 Node* AsyncBuiltinsAssembler::AllocateAsyncIteratorValueUnwrapContext(
300 Node* native_context, Node* done) {
301 CSA_ASSERT(
this, IsNativeContext(native_context));
302 CSA_ASSERT(
this, IsBoolean(done));
304 Node*
const context =
305 CreatePromiseContext(native_context, ValueUnwrapContext::kLength);
306 StoreContextElementNoWriteBarrier(context, ValueUnwrapContext::kDoneSlot,
311 TF_BUILTIN(AsyncIteratorValueUnwrap, AsyncBuiltinsAssembler) {
312 Node*
const value = Parameter(Descriptor::kValue);
313 Node*
const context = Parameter(Descriptor::kContext);
315 Node*
const done = LoadContextElement(context, ValueUnwrapContext::kDoneSlot);
316 CSA_ASSERT(
this, IsBoolean(done));
318 Node*
const unwrapped_value =
319 CallBuiltin(Builtins::kCreateIterResultObject, context, value, done);
321 Return(unwrapped_value);