20class AsyncGeneratorBuiltinsAssembler :
public AsyncBuiltinsAssembler {
23 : AsyncBuiltinsAssembler(state) {}
25 inline TNode<Smi> LoadGeneratorState(
26 const TNode<JSGeneratorObject> generator) {
27 return LoadObjectField<Smi>(generator,
28 JSGeneratorObject::kContinuationOffset);
31 inline TNode<BoolT> IsGeneratorStateClosed(
const TNode<Smi> state) {
34 inline TNode<BoolT> IsGeneratorClosed(
35 const TNode<JSGeneratorObject> generator) {
36 return IsGeneratorStateClosed(LoadGeneratorState(generator));
39 inline TNode<BoolT> IsGeneratorStateSuspended(
const TNode<Smi> state) {
40 return SmiGreaterThanOrEqual(state, SmiConstant(0));
43 inline TNode<BoolT> IsGeneratorSuspended(
44 const TNode<JSGeneratorObject> generator) {
45 return IsGeneratorStateSuspended(LoadGeneratorState(generator));
48 inline TNode<BoolT> IsGeneratorStateSuspendedAtStart(
const TNode<Smi> state) {
49 return SmiEqual(state, SmiConstant(0));
52 inline TNode<BoolT> IsGeneratorStateNotExecuting(
const TNode<Smi> state) {
53 return SmiNotEqual(state,
56 inline TNode<BoolT> IsGeneratorNotExecuting(
57 const TNode<JSGeneratorObject> generator) {
58 return IsGeneratorStateNotExecuting(LoadGeneratorState(generator));
61 inline TNode<BoolT> IsGeneratorAwaiting(
62 const TNode<JSGeneratorObject> generator) {
63 TNode<Object> is_generator_awaiting =
64 LoadObjectField(generator, JSAsyncGeneratorObject::kIsAwaitingOffset);
65 return TaggedEqual(is_generator_awaiting, SmiConstant(1));
68 inline void SetGeneratorAwaiting(
const TNode<JSGeneratorObject> generator) {
69 CSA_DCHECK(
this, Word32BinaryNot(IsGeneratorAwaiting(generator)));
70 StoreObjectFieldNoWriteBarrier(
71 generator, JSAsyncGeneratorObject::kIsAwaitingOffset, SmiConstant(1));
72 CSA_DCHECK(
this, IsGeneratorAwaiting(generator));
75 inline void SetGeneratorNotAwaiting(
76 const TNode<JSGeneratorObject> generator) {
77 CSA_DCHECK(
this, IsGeneratorAwaiting(generator));
78 StoreObjectFieldNoWriteBarrier(
79 generator, JSAsyncGeneratorObject::kIsAwaitingOffset, SmiConstant(0));
80 CSA_DCHECK(
this, Word32BinaryNot(IsGeneratorAwaiting(generator)));
83 inline void CloseGenerator(
const TNode<JSGeneratorObject> generator) {
84 StoreObjectFieldNoWriteBarrier(
85 generator, JSGeneratorObject::kContinuationOffset,
89 inline TNode<HeapObject> LoadFirstAsyncGeneratorRequestFromQueue(
90 const TNode<JSGeneratorObject> generator) {
91 return LoadObjectField<HeapObject>(generator,
92 JSAsyncGeneratorObject::kQueueOffset);
95 inline TNode<Smi> LoadResumeTypeFromAsyncGeneratorRequest(
96 const TNode<AsyncGeneratorRequest> request) {
97 return LoadObjectField<Smi>(request,
98 AsyncGeneratorRequest::kResumeModeOffset);
101 inline TNode<JSPromise> LoadPromiseFromAsyncGeneratorRequest(
102 const TNode<AsyncGeneratorRequest> request) {
103 return LoadObjectField<JSPromise>(request,
104 AsyncGeneratorRequest::kPromiseOffset);
107 inline TNode<Object> LoadValueFromAsyncGeneratorRequest(
108 const TNode<AsyncGeneratorRequest> request) {
109 return LoadObjectField(request, AsyncGeneratorRequest::kValueOffset);
112 inline TNode<BoolT> IsAbruptResumeType(
const TNode<Smi> resume_type) {
116 void AsyncGeneratorEnqueue(CodeStubArguments*
args, TNode<Context> context,
117 TNode<Object>
receiver, TNode<Object> value,
118 JSAsyncGeneratorObject::ResumeMode resume_mode,
119 const char* method_name);
121 TNode<AsyncGeneratorRequest> TakeFirstAsyncGeneratorRequestFromQueue(
122 TNode<JSAsyncGeneratorObject> generator);
123 void AddAsyncGeneratorRequestToQueue(TNode<JSAsyncGeneratorObject> generator,
124 TNode<AsyncGeneratorRequest> request);
126 TNode<AsyncGeneratorRequest> AllocateAsyncGeneratorRequest(
127 JSAsyncGeneratorObject::ResumeMode resume_mode,
128 TNode<Object> resume_value, TNode<JSPromise> promise);
132 template <
typename Descriptor>
133 void AsyncGeneratorAwait();
134 void AsyncGeneratorAwaitResume(
135 TNode<Context> context,
136 TNode<JSAsyncGeneratorObject> async_generator_object, TNode<Object> value,
137 JSAsyncGeneratorObject::ResumeMode resume_mode);
138 void AsyncGeneratorAwaitResumeClosure(
139 TNode<Context> context, TNode<Object> value,
140 JSAsyncGeneratorObject::ResumeMode resume_mode);
141 void AsyncGeneratorReturnClosedReject(
142 TNode<Context> context,
143 TNode<JSAsyncGeneratorObject> async_generator_object,
144 TNode<Object> value);
149void AsyncGeneratorBuiltinsAssembler::AsyncGeneratorEnqueue(
150 CodeStubArguments*
args, TNode<Context> context, TNode<Object>
receiver,
151 TNode<Object> value, JSAsyncGeneratorObject::ResumeMode resume_mode,
152 const char* method_name) {
158 TNode<JSPromise> promise = NewJSPromise(context);
160 Label if_receiverisincompatible(
this, Label::kDeferred);
161 GotoIf(TaggedIsSmi(
receiver), &if_receiverisincompatible);
162 GotoIfNot(HasInstanceType(
CAST(
receiver), JS_ASYNC_GENERATOR_OBJECT_TYPE),
163 &if_receiverisincompatible);
167 const TNode<JSAsyncGeneratorObject> generator =
CAST(
receiver);
168 const TNode<AsyncGeneratorRequest> req =
169 AllocateAsyncGeneratorRequest(resume_mode, value, promise);
171 AddAsyncGeneratorRequestToQueue(generator, req);
177 TNode<Smi>
continuation = LoadGeneratorState(generator);
180 SmiConstant(JSAsyncGeneratorObject::kGeneratorExecuting)),
183 CallBuiltin(Builtin::kAsyncGeneratorResumeNext, context, generator);
187 args->PopAndReturn(promise);
190 BIND(&if_receiverisincompatible);
192 CallBuiltin(Builtin::kRejectPromise, context, promise,
193 MakeTypeError(MessageTemplate::kIncompatibleMethodReceiver,
194 context, StringConstant(method_name),
receiver),
196 args->PopAndReturn(promise);
200TNode<AsyncGeneratorRequest>
201AsyncGeneratorBuiltinsAssembler::AllocateAsyncGeneratorRequest(
202 JSAsyncGeneratorObject::ResumeMode resume_mode, TNode<Object> resume_value,
203 TNode<JSPromise> promise) {
204 TNode<HeapObject> request =
Allocate(AsyncGeneratorRequest::kSize);
205 StoreMapNoWriteBarrier(request, RootIndex::kAsyncGeneratorRequestMap);
206 StoreObjectFieldNoWriteBarrier(request, AsyncGeneratorRequest::kNextOffset,
208 StoreObjectFieldNoWriteBarrier(request,
209 AsyncGeneratorRequest::kResumeModeOffset,
210 SmiConstant(resume_mode));
211 StoreObjectFieldNoWriteBarrier(request, AsyncGeneratorRequest::kValueOffset,
213 StoreObjectFieldNoWriteBarrier(request, AsyncGeneratorRequest::kPromiseOffset,
215 StoreObjectFieldRoot(request, AsyncGeneratorRequest::kNextOffset,
216 RootIndex::kUndefinedValue);
217 return CAST(request);
220void AsyncGeneratorBuiltinsAssembler::AsyncGeneratorAwaitResume(
221 TNode<Context> context,
222 TNode<JSAsyncGeneratorObject> async_generator_object, TNode<Object> value,
223 JSAsyncGeneratorObject::ResumeMode resume_mode) {
224 SetGeneratorNotAwaiting(async_generator_object);
229 StoreObjectFieldNoWriteBarrier(async_generator_object,
230 JSGeneratorObject::kResumeModeOffset,
231 SmiConstant(resume_mode));
233 CallBuiltin(Builtin::kResumeGeneratorTrampoline, context, value,
234 async_generator_object);
236 TailCallBuiltin(Builtin::kAsyncGeneratorResumeNext, context,
237 async_generator_object);
240void AsyncGeneratorBuiltinsAssembler::AsyncGeneratorAwaitResumeClosure(
241 TNode<Context> context, TNode<Object> value,
242 JSAsyncGeneratorObject::ResumeMode resume_mode) {
243 const TNode<JSAsyncGeneratorObject> async_generator_object =
244 CAST(LoadContextElement(context, Context::EXTENSION_INDEX));
246 AsyncGeneratorAwaitResume(context, async_generator_object, value,
250template <
typename Descriptor>
251void AsyncGeneratorBuiltinsAssembler::AsyncGeneratorAwait() {
252 auto async_generator_object =
253 Parameter<JSAsyncGeneratorObject>(Descriptor::kAsyncGeneratorObject);
254 auto value = Parameter<JSAny>(Descriptor::kValue);
255 auto context = Parameter<Context>(Descriptor::kContext);
257 TNode<AsyncGeneratorRequest> request =
258 CAST(LoadFirstAsyncGeneratorRequestFromQueue(async_generator_object));
259 TNode<JSPromise> outer_promise = LoadObjectField<JSPromise>(
260 request, AsyncGeneratorRequest::kPromiseOffset);
262 Await(context, async_generator_object, value, outer_promise,
263 RootIndex::kAsyncGeneratorAwaitResolveClosureSharedFun,
264 RootIndex::kAsyncGeneratorAwaitRejectClosureSharedFun);
265 SetGeneratorAwaiting(async_generator_object);
269void AsyncGeneratorBuiltinsAssembler::AddAsyncGeneratorRequestToQueue(
270 TNode<JSAsyncGeneratorObject> generator,
271 TNode<AsyncGeneratorRequest> request) {
273 Label empty(
this), loop(
this, &var_current), done(
this);
275 var_current = LoadObjectField<HeapObject>(
276 generator, JSAsyncGeneratorObject::kQueueOffset);
277 Branch(IsUndefined(var_current.value()), &empty, &loop);
281 StoreObjectField(generator, JSAsyncGeneratorObject::kQueueOffset, request);
287 Label loop_next(
this), next_empty(
this);
288 TNode<AsyncGeneratorRequest> current =
CAST(var_current.value());
289 TNode<HeapObject> next = LoadObjectField<HeapObject>(
290 current, AsyncGeneratorRequest::kNextOffset);
292 Branch(IsUndefined(next), &next_empty, &loop_next);
295 StoreObjectField(current, AsyncGeneratorRequest::kNextOffset, request);
308TNode<AsyncGeneratorRequest>
309AsyncGeneratorBuiltinsAssembler::TakeFirstAsyncGeneratorRequestFromQueue(
310 TNode<JSAsyncGeneratorObject> generator) {
313 TNode<AsyncGeneratorRequest> request = LoadObjectField<AsyncGeneratorRequest>(
314 generator, JSAsyncGeneratorObject::kQueueOffset);
317 LoadObjectField(request, AsyncGeneratorRequest::kNextOffset);
319 StoreObjectField(generator, JSAsyncGeneratorObject::kQueueOffset, next);
323void AsyncGeneratorBuiltinsAssembler::AsyncGeneratorReturnClosedReject(
324 TNode<Context> context, TNode<JSAsyncGeneratorObject> generator,
325 TNode<Object> value) {
326 SetGeneratorNotAwaiting(generator);
331 CallBuiltin(Builtin::kAsyncGeneratorReject, context, generator, value);
333 TailCallBuiltin(Builtin::kAsyncGeneratorResumeNext, context, generator);
339TF_BUILTIN(AsyncGeneratorPrototypeNext, AsyncGeneratorBuiltinsAssembler) {
340 const int kValueArg = 0;
343 UncheckedParameter<Int32T>(Descriptor::kJSActualArgumentsCount));
348 auto context = Parameter<Context>(Descriptor::kContext);
350 AsyncGeneratorEnqueue(&
args, context, generator, value,
351 JSAsyncGeneratorObject::kNext,
352 "[AsyncGenerator].prototype.next");
357TF_BUILTIN(AsyncGeneratorPrototypeReturn, AsyncGeneratorBuiltinsAssembler) {
358 const int kValueArg = 0;
361 UncheckedParameter<Int32T>(Descriptor::kJSActualArgumentsCount));
366 auto context = Parameter<Context>(Descriptor::kContext);
368 AsyncGeneratorEnqueue(&
args, context, generator, value,
369 JSAsyncGeneratorObject::kReturn,
370 "[AsyncGenerator].prototype.return");
375TF_BUILTIN(AsyncGeneratorPrototypeThrow, AsyncGeneratorBuiltinsAssembler) {
376 const int kValueArg = 0;
379 UncheckedParameter<Int32T>(Descriptor::kJSActualArgumentsCount));
384 auto context = Parameter<Context>(Descriptor::kContext);
386 AsyncGeneratorEnqueue(&
args, context, generator, value,
387 JSAsyncGeneratorObject::kThrow,
388 "[AsyncGenerator].prototype.throw");
391TF_BUILTIN(AsyncGeneratorAwaitResolveClosure, AsyncGeneratorBuiltinsAssembler) {
392 auto value = Parameter<JSAny>(Descriptor::kValue);
393 auto context = Parameter<Context>(Descriptor::kContext);
394 AsyncGeneratorAwaitResumeClosure(context, value,
395 JSAsyncGeneratorObject::kNext);
398TF_BUILTIN(AsyncGeneratorAwaitRejectClosure, AsyncGeneratorBuiltinsAssembler) {
399 auto value = Parameter<JSAny>(Descriptor::kValue);
400 auto context = Parameter<Context>(Descriptor::kContext);
403 AsyncGeneratorAwaitResumeClosure(context, value,
404 JSAsyncGeneratorObject::kRethrow);
407TF_BUILTIN(AsyncGeneratorAwait, AsyncGeneratorBuiltinsAssembler) {
408 AsyncGeneratorAwait<Descriptor>();
411TF_BUILTIN(AsyncGeneratorResumeNext, AsyncGeneratorBuiltinsAssembler) {
412 const auto generator =
413 Parameter<JSAsyncGeneratorObject>(Descriptor::kGenerator);
414 const auto context = Parameter<Context>(Descriptor::kContext);
424 TVARIABLE(
Smi, var_state, LoadGeneratorState(generator));
426 LoadFirstAsyncGeneratorRequestFromQueue(generator));
431 CSA_DCHECK(
this, IsGeneratorNotExecuting(generator));
434 ReturnIf(IsGeneratorAwaiting(generator), UndefinedConstant());
437 ReturnIf(IsUndefined(var_next.value()), UndefinedConstant());
440 const TNode<Smi> resume_type = LoadResumeTypeFromAsyncGeneratorRequest(next);
442 Label if_abrupt(
this), if_normal(
this), resume_generator(
this);
443 Branch(IsAbruptResumeType(resume_type), &if_abrupt, &if_normal);
446 Label settle_promise(
this), if_return(
this), if_throw(
this);
447 GotoIfNot(IsGeneratorStateSuspendedAtStart(var_state.value()),
449 CloseGenerator(generator);
451 Goto(&settle_promise);
453 BIND(&settle_promise);
454 TNode<Object> next_value = LoadValueFromAsyncGeneratorRequest(next);
456 &if_return, &if_throw);
466 TailCallBuiltin(Builtin::kAsyncGeneratorReturn, context, generator,
470 GotoIfNot(IsGeneratorStateClosed(var_state.value()), &resume_generator);
471 CallBuiltin(Builtin::kAsyncGeneratorReject, context, generator, next_value);
472 var_next = LoadFirstAsyncGeneratorRequestFromQueue(generator);
478 GotoIfNot(IsGeneratorStateClosed(var_state.value()), &resume_generator);
479 CallBuiltin(Builtin::kAsyncGeneratorResolve, context, generator,
480 UndefinedConstant(), TrueConstant());
481 var_state = LoadGeneratorState(generator);
482 var_next = LoadFirstAsyncGeneratorRequestFromQueue(generator);
486 BIND(&resume_generator);
489 StoreObjectFieldNoWriteBarrier(
490 generator, JSGeneratorObject::kResumeModeOffset, resume_type);
492 CallBuiltin(Builtin::kResumeGeneratorTrampoline, context,
493 LoadValueFromAsyncGeneratorRequest(next), generator);
494 var_state = LoadGeneratorState(generator);
495 var_next = LoadFirstAsyncGeneratorRequestFromQueue(generator);
500TF_BUILTIN(AsyncGeneratorResolve, AsyncGeneratorBuiltinsAssembler) {
501 const auto generator =
502 Parameter<JSAsyncGeneratorObject>(Descriptor::kGenerator);
503 const auto value = Parameter<JSAny>(Descriptor::kValue);
504 const auto done = Parameter<Object>(Descriptor::kDone);
505 const auto context = Parameter<Context>(Descriptor::kContext);
507 CSA_DCHECK(
this, Word32BinaryNot(IsGeneratorAwaiting(generator)));
516 TakeFirstAsyncGeneratorRequestFromQueue(generator);
517 const TNode<JSPromise> promise = LoadPromiseFromAsyncGeneratorRequest(next);
523 LoadNativeContext(context), Context::ITERATOR_RESULT_MAP_INDEX));
524 StoreMapNoWriteBarrier(iter_result, map);
525 StoreObjectFieldRoot(iter_result, JSIteratorResult::kPropertiesOrHashOffset,
526 RootIndex::kEmptyFixedArray);
527 StoreObjectFieldRoot(iter_result, JSIteratorResult::kElementsOffset,
528 RootIndex::kEmptyFixedArray);
529 StoreObjectFieldNoWriteBarrier(iter_result, JSIteratorResult::kValueOffset,
531 StoreObjectFieldNoWriteBarrier(iter_result, JSIteratorResult::kDoneOffset,
544 Label if_fast(
this), if_slow(
this, Label::kDeferred), return_promise(
this);
545 GotoIfForceSlowPath(&if_slow);
546 GotoIf(IsIsolatePromiseHookEnabledOrHasAsyncEventDelegate(), &if_slow);
547 Branch(IsPromiseThenProtectorCellInvalid(), &if_slow, &if_fast);
553 CallBuiltin(Builtin::kFulfillPromise, context, promise, iter_result);
554 Goto(&return_promise);
560 CallBuiltin(Builtin::kResolvePromise, context, promise, iter_result);
561 Goto(&return_promise);
566 BIND(&return_promise);
570TF_BUILTIN(AsyncGeneratorReject, AsyncGeneratorBuiltinsAssembler) {
571 const auto generator =
572 Parameter<JSAsyncGeneratorObject>(Descriptor::kGenerator);
573 const auto value = Parameter<JSAny>(Descriptor::kValue);
574 const auto context = Parameter<Context>(Descriptor::kContext);
577 TakeFirstAsyncGeneratorRequestFromQueue(generator);
581 Return(CallBuiltin(Builtin::kRejectPromise, context, promise, value,
585TF_BUILTIN(AsyncGeneratorYieldWithAwait, AsyncGeneratorBuiltinsAssembler) {
586 const auto generator = Parameter<JSGeneratorObject>(Descriptor::kGenerator);
587 const auto value = Parameter<JSAny>(Descriptor::kValue);
588 const auto context = Parameter<Context>(Descriptor::kContext);
591 CAST(LoadFirstAsyncGeneratorRequestFromQueue(generator));
593 LoadPromiseFromAsyncGeneratorRequest(request);
595 Await(context, generator, value, outer_promise,
596 RootIndex::kAsyncGeneratorYieldWithAwaitResolveClosureSharedFun,
597 RootIndex::kAsyncGeneratorAwaitRejectClosureSharedFun);
598 SetGeneratorAwaiting(generator);
599 Return(UndefinedConstant());
603 AsyncGeneratorBuiltinsAssembler) {
604 const auto context = Parameter<Context>(Descriptor::kContext);
605 const auto value = Parameter<JSAny>(Descriptor::kValue);
609 SetGeneratorNotAwaiting(generator);
613 CallBuiltin(Builtin::kAsyncGeneratorResolve, context, generator, value,
616 TailCallBuiltin(Builtin::kAsyncGeneratorResumeNext, context, generator);
619TF_BUILTIN(AsyncGeneratorReturn, AsyncGeneratorBuiltinsAssembler) {
636 const auto generator =
637 Parameter<JSAsyncGeneratorObject>(Descriptor::kGenerator);
638 const auto value = Parameter<JSAny>(Descriptor::kValue);
640 CAST(LoadFirstAsyncGeneratorRequestFromQueue(generator));
642 const TNode<Smi> state = LoadGeneratorState(generator);
647 Label closed(
this), not_closed(
this), done(
this);
648 Branch(IsGeneratorStateClosed(state), &closed, ¬_closed);
651 var_on_resolve = AllocateRootFunctionWithContext(
652 RootIndex::kAsyncGeneratorReturnClosedResolveClosureSharedFun, context,
654 var_on_reject = AllocateRootFunctionWithContext(
655 RootIndex::kAsyncGeneratorReturnClosedRejectClosureSharedFun, context,
660 var_on_resolve = AllocateRootFunctionWithContext(
661 RootIndex::kAsyncGeneratorReturnResolveClosureSharedFun, context,
663 var_on_reject = AllocateRootFunctionWithContext(
664 RootIndex::kAsyncGeneratorAwaitRejectClosureSharedFun, context,
669 return std::make_pair(var_on_resolve.value(), var_on_reject.value());
672 SetGeneratorAwaiting(generator);
673 auto context = Parameter<Context>(Descriptor::kContext);
675 LoadPromiseFromAsyncGeneratorRequest(req);
677 Label done(
this), await_exception(
this, Label::kDeferred),
678 closed_await_exception(
this, Label::kDeferred);
683 Await(context, generator, value, outer_promise, MakeClosures);
687 BIND(&await_exception);
689 GotoIf(IsGeneratorStateClosed(state), &closed_await_exception);
691 AsyncGeneratorAwaitResume(context, generator, var_exception.value(),
695 BIND(&closed_await_exception);
698 AsyncGeneratorReturnClosedReject(context, generator, var_exception.value());
702 Return(UndefinedConstant());
710 AsyncGeneratorBuiltinsAssembler) {
711 const auto context = Parameter<Context>(Descriptor::kContext);
712 const auto value = Parameter<JSAny>(Descriptor::kValue);
720 AsyncGeneratorBuiltinsAssembler) {
721 const auto context = Parameter<Context>(Descriptor::kContext);
722 const auto value = Parameter<JSAny>(Descriptor::kValue);
726 SetGeneratorNotAwaiting(generator);
731 CallBuiltin(Builtin::kAsyncGeneratorResolve, context, generator, value,
734 TailCallBuiltin(Builtin::kAsyncGeneratorResumeNext, context, generator);
738 AsyncGeneratorBuiltinsAssembler) {
739 const auto context = Parameter<Context>(Descriptor::kContext);
740 const auto value = Parameter<JSAny>(Descriptor::kValue);
744 AsyncGeneratorReturnClosedReject(context, generator, value);
#define CSA_SLOW_DCHECK(csa,...)
#define CSA_DCHECK(csa,...)
#define TF_BUILTIN(Name, AssemblerBase)
static const int kGeneratorClosed
static const int kGeneratorExecuting
base::Vector< const DirectHandle< Object > > args
MovableLabel continuation
void * Allocate(void *address, size_t size, OS::MemoryPermission access)
TNode< Oddball > UndefinedConstant(JSGraph *jsgraph)
compiler::CodeAssemblerState CodeAssemblerState
!IsContextMap !IsContextMap native_context