5 #include "src/builtins/builtins-async-gen.h" 6 #include "src/builtins/builtins-utils-gen.h" 7 #include "src/builtins/builtins.h" 8 #include "src/code-stub-assembler.h" 9 #include "src/objects-inl.h" 10 #include "src/objects/js-generator.h" 11 #include "src/objects/js-promise.h" 22 template <
typename Descriptor>
23 void AsyncFunctionAwait(
const bool is_predicted_as_caught);
25 void AsyncFunctionAwaitResumeClosure(
26 Node*
const context,
Node*
const sent_value,
27 JSGeneratorObject::ResumeMode resume_mode);
30 void AsyncFunctionBuiltinsAssembler::AsyncFunctionAwaitResumeClosure(
32 JSGeneratorObject::ResumeMode resume_mode) {
33 DCHECK(resume_mode == JSGeneratorObject::kNext ||
34 resume_mode == JSGeneratorObject::kThrow);
37 CAST(LoadContextElement(context, Context::EXTENSION_INDEX));
45 LoadObjectField<Smi>(async_function_object,
46 JSGeneratorObject::kContinuationOffset),
47 SmiConstant(JSGeneratorObject::kGeneratorClosed)));
50 StoreObjectFieldNoWriteBarrier(async_function_object,
51 JSGeneratorObject::kResumeModeOffset,
52 SmiConstant(resume_mode));
55 Callable callable = CodeFactory::ResumeGenerator(isolate());
56 CallStub(callable, context, sent_value, async_function_object);
64 TF_BUILTIN(AsyncFunctionEnter, AsyncFunctionBuiltinsAssembler) {
65 TNode<JSFunction> closure = CAST(Parameter(Descriptor::kClosure));
66 TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
67 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
70 TNode<SharedFunctionInfo> shared = LoadObjectField<SharedFunctionInfo>(
71 closure, JSFunction::kSharedFunctionInfoOffset);
72 TNode<IntPtrT> formal_parameter_count = ChangeInt32ToIntPtr(
73 LoadObjectField(shared, SharedFunctionInfo::kFormalParameterCountOffset,
74 MachineType::Uint16()));
75 TNode<BytecodeArray> bytecode_array =
76 LoadSharedFunctionInfoBytecodeArray(shared);
77 TNode<IntPtrT> frame_size = ChangeInt32ToIntPtr(LoadObjectField(
78 bytecode_array, BytecodeArray::kFrameSizeOffset, MachineType::Int32()));
79 TNode<IntPtrT> parameters_and_register_length =
80 Signed(IntPtrAdd(WordSar(frame_size, IntPtrConstant(kPointerSizeLog2)),
81 formal_parameter_count));
85 TNode<IntPtrT> size = IntPtrAdd(
86 IntPtrConstant(JSPromise::kSizeWithEmbedderFields +
87 JSAsyncFunctionObject::kSize + FixedArray::kHeaderSize),
88 Signed(WordShl(parameters_and_register_length,
89 IntPtrConstant(kPointerSizeLog2))));
90 TNode<HeapObject> base = AllocateInNewSpace(size);
93 TNode<FixedArray> parameters_and_registers = UncheckedCast<FixedArray>(
94 InnerAllocate(base, JSAsyncFunctionObject::kSize +
95 JSPromise::kSizeWithEmbedderFields));
96 StoreMapNoWriteBarrier(parameters_and_registers, RootIndex::kFixedArrayMap);
97 StoreObjectFieldNoWriteBarrier(parameters_and_registers,
98 FixedArray::kLengthOffset,
99 SmiFromIntPtr(parameters_and_register_length));
100 FillFixedArrayWithValue(HOLEY_ELEMENTS, parameters_and_registers,
101 IntPtrConstant(0), parameters_and_register_length,
102 RootIndex::kUndefinedValue);
105 TNode<Context> native_context = LoadNativeContext(context);
106 TNode<JSFunction> promise_function =
107 CAST(LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX));
108 TNode<Map> promise_map = LoadObjectField<Map>(
109 promise_function, JSFunction::kPrototypeOrInitialMapOffset);
110 TNode<JSPromise> promise = UncheckedCast<JSPromise>(
111 InnerAllocate(base, JSAsyncFunctionObject::kSize));
112 StoreMapNoWriteBarrier(promise, promise_map);
113 StoreObjectFieldRoot(promise, JSPromise::kPropertiesOrHashOffset,
114 RootIndex::kEmptyFixedArray);
115 StoreObjectFieldRoot(promise, JSPromise::kElementsOffset,
116 RootIndex::kEmptyFixedArray);
117 PromiseInit(promise);
120 TNode<Map> async_function_object_map = CAST(LoadContextElement(
121 native_context, Context::ASYNC_FUNCTION_OBJECT_MAP_INDEX));
122 TNode<JSAsyncFunctionObject> async_function_object =
123 UncheckedCast<JSAsyncFunctionObject>(base);
124 StoreMapNoWriteBarrier(async_function_object, async_function_object_map);
125 StoreObjectFieldRoot(async_function_object,
126 JSAsyncFunctionObject::kPropertiesOrHashOffset,
127 RootIndex::kEmptyFixedArray);
128 StoreObjectFieldRoot(async_function_object,
129 JSAsyncFunctionObject::kElementsOffset,
130 RootIndex::kEmptyFixedArray);
131 StoreObjectFieldNoWriteBarrier(
132 async_function_object, JSAsyncFunctionObject::kFunctionOffset, closure);
133 StoreObjectFieldNoWriteBarrier(
134 async_function_object, JSAsyncFunctionObject::kContextOffset, context);
135 StoreObjectFieldNoWriteBarrier(
136 async_function_object, JSAsyncFunctionObject::kReceiverOffset, receiver);
137 StoreObjectFieldNoWriteBarrier(async_function_object,
138 JSAsyncFunctionObject::kInputOrDebugPosOffset,
140 StoreObjectFieldNoWriteBarrier(async_function_object,
141 JSAsyncFunctionObject::kResumeModeOffset,
142 SmiConstant(JSAsyncFunctionObject::kNext));
143 StoreObjectFieldNoWriteBarrier(
144 async_function_object, JSAsyncFunctionObject::kContinuationOffset,
145 SmiConstant(JSAsyncFunctionObject::kGeneratorExecuting));
146 StoreObjectFieldNoWriteBarrier(
147 async_function_object,
148 JSAsyncFunctionObject::kParametersAndRegistersOffset,
149 parameters_and_registers);
150 StoreObjectFieldNoWriteBarrier(
151 async_function_object, JSAsyncFunctionObject::kPromiseOffset, promise);
156 Label if_instrumentation(
this, Label::kDeferred),
157 if_instrumentation_done(
this);
158 Branch(IsPromiseHookEnabledOrDebugIsActiveOrHasAsyncEventDelegate(),
159 &if_instrumentation, &if_instrumentation_done);
160 BIND(&if_instrumentation);
162 CallRuntime(Runtime::kDebugAsyncFunctionEntered, context, promise);
163 Goto(&if_instrumentation_done);
165 BIND(&if_instrumentation_done);
167 Return(async_function_object);
170 TF_BUILTIN(AsyncFunctionReject, AsyncFunctionBuiltinsAssembler) {
171 TNode<JSAsyncFunctionObject> async_function_object =
172 CAST(Parameter(Descriptor::kAsyncFunctionObject));
173 TNode<Object> reason = CAST(Parameter(Descriptor::kReason));
174 TNode<Oddball> can_suspend = CAST(Parameter(Descriptor::kCanSuspend));
175 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
176 TNode<JSPromise> promise = LoadObjectField<JSPromise>(
177 async_function_object, JSAsyncFunctionObject::kPromiseOffset);
182 CallBuiltin(Builtins::kRejectPromise, context, promise, reason,
185 Label if_debugging(
this, Label::kDeferred);
186 GotoIf(HasAsyncEventDelegate(), &if_debugging);
187 GotoIf(IsDebugActive(), &if_debugging);
191 TailCallRuntime(Runtime::kDebugAsyncFunctionFinished, context, can_suspend,
195 TF_BUILTIN(AsyncFunctionResolve, AsyncFunctionBuiltinsAssembler) {
196 TNode<JSAsyncFunctionObject> async_function_object =
197 CAST(Parameter(Descriptor::kAsyncFunctionObject));
198 TNode<Object> value = CAST(Parameter(Descriptor::kValue));
199 TNode<Oddball> can_suspend = CAST(Parameter(Descriptor::kCanSuspend));
200 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
201 TNode<JSPromise> promise = LoadObjectField<JSPromise>(
202 async_function_object, JSAsyncFunctionObject::kPromiseOffset);
204 CallBuiltin(Builtins::kResolvePromise, context, promise, value);
206 Label if_debugging(
this, Label::kDeferred);
207 GotoIf(HasAsyncEventDelegate(), &if_debugging);
208 GotoIf(IsDebugActive(), &if_debugging);
212 TailCallRuntime(Runtime::kDebugAsyncFunctionFinished, context, can_suspend,
219 TF_BUILTIN(AsyncFunctionLazyDeoptContinuation, AsyncFunctionBuiltinsAssembler) {
220 TNode<JSPromise> promise = CAST(Parameter(Descriptor::kPromise));
224 TF_BUILTIN(AsyncFunctionAwaitRejectClosure, AsyncFunctionBuiltinsAssembler) {
225 CSA_ASSERT_JS_ARGC_EQ(
this, 1);
226 Node*
const sentError = Parameter(Descriptor::kSentError);
227 Node*
const context = Parameter(Descriptor::kContext);
229 AsyncFunctionAwaitResumeClosure(context, sentError,
230 JSGeneratorObject::kThrow);
231 Return(UndefinedConstant());
234 TF_BUILTIN(AsyncFunctionAwaitResolveClosure, AsyncFunctionBuiltinsAssembler) {
235 CSA_ASSERT_JS_ARGC_EQ(
this, 1);
236 Node*
const sentValue = Parameter(Descriptor::kSentValue);
237 Node*
const context = Parameter(Descriptor::kContext);
239 AsyncFunctionAwaitResumeClosure(context, sentValue, JSGeneratorObject::kNext);
240 Return(UndefinedConstant());
251 template <
typename Descriptor>
252 void AsyncFunctionBuiltinsAssembler::AsyncFunctionAwait(
253 const bool is_predicted_as_caught) {
254 TNode<JSAsyncFunctionObject> async_function_object =
255 CAST(Parameter(Descriptor::kAsyncFunctionObject));
256 TNode<Object> value = CAST(Parameter(Descriptor::kValue));
257 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
259 Node* outer_promise = LoadObjectField(async_function_object,
260 JSAsyncFunctionObject::kPromiseOffset);
262 Label after_debug_hook(
this), call_debug_hook(
this, Label::kDeferred);
263 GotoIf(HasAsyncEventDelegate(), &call_debug_hook);
264 Goto(&after_debug_hook);
265 BIND(&after_debug_hook);
267 Await(context, async_function_object, value, outer_promise,
268 Context::ASYNC_FUNCTION_AWAIT_RESOLVE_SHARED_FUN,
269 Context::ASYNC_FUNCTION_AWAIT_REJECT_SHARED_FUN,
270 is_predicted_as_caught);
274 Return(outer_promise);
276 BIND(&call_debug_hook);
277 CallRuntime(Runtime::kDebugAsyncFunctionSuspended, context, outer_promise);
278 Goto(&after_debug_hook);
283 TF_BUILTIN(AsyncFunctionAwaitCaught, AsyncFunctionBuiltinsAssembler) {
284 static const bool kIsPredictedAsCaught =
true;
285 AsyncFunctionAwait<Descriptor>(kIsPredictedAsCaught);
290 TF_BUILTIN(AsyncFunctionAwaitUncaught, AsyncFunctionBuiltinsAssembler) {
291 static const bool kIsPredictedAsCaught =
false;
292 AsyncFunctionAwait<Descriptor>(kIsPredictedAsCaught);