11cb0ef41Sopenharmony_ci// Copyright 2017 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#include "src/builtins/builtins-async-gen.h"
61cb0ef41Sopenharmony_ci#include "src/builtins/builtins-utils-gen.h"
71cb0ef41Sopenharmony_ci#include "src/builtins/builtins.h"
81cb0ef41Sopenharmony_ci#include "src/codegen/code-factory.h"
91cb0ef41Sopenharmony_ci#include "src/codegen/code-stub-assembler.h"
101cb0ef41Sopenharmony_ci#include "src/execution/frames-inl.h"
111cb0ef41Sopenharmony_ci#include "src/objects/js-generator.h"
121cb0ef41Sopenharmony_ci#include "src/objects/js-promise.h"
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_cinamespace v8 {
151cb0ef41Sopenharmony_cinamespace internal {
161cb0ef41Sopenharmony_ci
171cb0ef41Sopenharmony_cinamespace {
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_ciclass AsyncGeneratorBuiltinsAssembler : public AsyncBuiltinsAssembler {
201cb0ef41Sopenharmony_ci public:
211cb0ef41Sopenharmony_ci  explicit AsyncGeneratorBuiltinsAssembler(CodeAssemblerState* state)
221cb0ef41Sopenharmony_ci      : AsyncBuiltinsAssembler(state) {}
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_ci  inline TNode<Smi> LoadGeneratorState(
251cb0ef41Sopenharmony_ci      const TNode<JSGeneratorObject> generator) {
261cb0ef41Sopenharmony_ci    return LoadObjectField<Smi>(generator,
271cb0ef41Sopenharmony_ci                                JSGeneratorObject::kContinuationOffset);
281cb0ef41Sopenharmony_ci  }
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ci  inline TNode<BoolT> IsGeneratorStateClosed(const TNode<Smi> state) {
311cb0ef41Sopenharmony_ci    return SmiEqual(state, SmiConstant(JSGeneratorObject::kGeneratorClosed));
321cb0ef41Sopenharmony_ci  }
331cb0ef41Sopenharmony_ci  inline TNode<BoolT> IsGeneratorClosed(
341cb0ef41Sopenharmony_ci      const TNode<JSGeneratorObject> generator) {
351cb0ef41Sopenharmony_ci    return IsGeneratorStateClosed(LoadGeneratorState(generator));
361cb0ef41Sopenharmony_ci  }
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_ci  inline TNode<BoolT> IsGeneratorStateSuspended(const TNode<Smi> state) {
391cb0ef41Sopenharmony_ci    return SmiGreaterThanOrEqual(state, SmiConstant(0));
401cb0ef41Sopenharmony_ci  }
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ci  inline TNode<BoolT> IsGeneratorSuspended(
431cb0ef41Sopenharmony_ci      const TNode<JSGeneratorObject> generator) {
441cb0ef41Sopenharmony_ci    return IsGeneratorStateSuspended(LoadGeneratorState(generator));
451cb0ef41Sopenharmony_ci  }
461cb0ef41Sopenharmony_ci
471cb0ef41Sopenharmony_ci  inline TNode<BoolT> IsGeneratorStateSuspendedAtStart(const TNode<Smi> state) {
481cb0ef41Sopenharmony_ci    return SmiEqual(state, SmiConstant(0));
491cb0ef41Sopenharmony_ci  }
501cb0ef41Sopenharmony_ci
511cb0ef41Sopenharmony_ci  inline TNode<BoolT> IsGeneratorStateNotExecuting(const TNode<Smi> state) {
521cb0ef41Sopenharmony_ci    return SmiNotEqual(state,
531cb0ef41Sopenharmony_ci                       SmiConstant(JSGeneratorObject::kGeneratorExecuting));
541cb0ef41Sopenharmony_ci  }
551cb0ef41Sopenharmony_ci  inline TNode<BoolT> IsGeneratorNotExecuting(
561cb0ef41Sopenharmony_ci      const TNode<JSGeneratorObject> generator) {
571cb0ef41Sopenharmony_ci    return IsGeneratorStateNotExecuting(LoadGeneratorState(generator));
581cb0ef41Sopenharmony_ci  }
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ci  inline TNode<BoolT> IsGeneratorAwaiting(
611cb0ef41Sopenharmony_ci      const TNode<JSGeneratorObject> generator) {
621cb0ef41Sopenharmony_ci    TNode<Object> is_generator_awaiting =
631cb0ef41Sopenharmony_ci        LoadObjectField(generator, JSAsyncGeneratorObject::kIsAwaitingOffset);
641cb0ef41Sopenharmony_ci    return TaggedEqual(is_generator_awaiting, SmiConstant(1));
651cb0ef41Sopenharmony_ci  }
661cb0ef41Sopenharmony_ci
671cb0ef41Sopenharmony_ci  inline void SetGeneratorAwaiting(const TNode<JSGeneratorObject> generator) {
681cb0ef41Sopenharmony_ci    CSA_DCHECK(this, Word32BinaryNot(IsGeneratorAwaiting(generator)));
691cb0ef41Sopenharmony_ci    StoreObjectFieldNoWriteBarrier(
701cb0ef41Sopenharmony_ci        generator, JSAsyncGeneratorObject::kIsAwaitingOffset, SmiConstant(1));
711cb0ef41Sopenharmony_ci    CSA_DCHECK(this, IsGeneratorAwaiting(generator));
721cb0ef41Sopenharmony_ci  }
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_ci  inline void SetGeneratorNotAwaiting(
751cb0ef41Sopenharmony_ci      const TNode<JSGeneratorObject> generator) {
761cb0ef41Sopenharmony_ci    CSA_DCHECK(this, IsGeneratorAwaiting(generator));
771cb0ef41Sopenharmony_ci    StoreObjectFieldNoWriteBarrier(
781cb0ef41Sopenharmony_ci        generator, JSAsyncGeneratorObject::kIsAwaitingOffset, SmiConstant(0));
791cb0ef41Sopenharmony_ci    CSA_DCHECK(this, Word32BinaryNot(IsGeneratorAwaiting(generator)));
801cb0ef41Sopenharmony_ci  }
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ci  inline void CloseGenerator(const TNode<JSGeneratorObject> generator) {
831cb0ef41Sopenharmony_ci    StoreObjectFieldNoWriteBarrier(
841cb0ef41Sopenharmony_ci        generator, JSGeneratorObject::kContinuationOffset,
851cb0ef41Sopenharmony_ci        SmiConstant(JSGeneratorObject::kGeneratorClosed));
861cb0ef41Sopenharmony_ci  }
871cb0ef41Sopenharmony_ci
881cb0ef41Sopenharmony_ci  inline TNode<HeapObject> LoadFirstAsyncGeneratorRequestFromQueue(
891cb0ef41Sopenharmony_ci      const TNode<JSGeneratorObject> generator) {
901cb0ef41Sopenharmony_ci    return LoadObjectField<HeapObject>(generator,
911cb0ef41Sopenharmony_ci                                       JSAsyncGeneratorObject::kQueueOffset);
921cb0ef41Sopenharmony_ci  }
931cb0ef41Sopenharmony_ci
941cb0ef41Sopenharmony_ci  inline TNode<Smi> LoadResumeTypeFromAsyncGeneratorRequest(
951cb0ef41Sopenharmony_ci      const TNode<AsyncGeneratorRequest> request) {
961cb0ef41Sopenharmony_ci    return LoadObjectField<Smi>(request,
971cb0ef41Sopenharmony_ci                                AsyncGeneratorRequest::kResumeModeOffset);
981cb0ef41Sopenharmony_ci  }
991cb0ef41Sopenharmony_ci
1001cb0ef41Sopenharmony_ci  inline TNode<JSPromise> LoadPromiseFromAsyncGeneratorRequest(
1011cb0ef41Sopenharmony_ci      const TNode<AsyncGeneratorRequest> request) {
1021cb0ef41Sopenharmony_ci    return LoadObjectField<JSPromise>(request,
1031cb0ef41Sopenharmony_ci                                      AsyncGeneratorRequest::kPromiseOffset);
1041cb0ef41Sopenharmony_ci  }
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ci  inline TNode<Object> LoadValueFromAsyncGeneratorRequest(
1071cb0ef41Sopenharmony_ci      const TNode<AsyncGeneratorRequest> request) {
1081cb0ef41Sopenharmony_ci    return LoadObjectField(request, AsyncGeneratorRequest::kValueOffset);
1091cb0ef41Sopenharmony_ci  }
1101cb0ef41Sopenharmony_ci
1111cb0ef41Sopenharmony_ci  inline TNode<BoolT> IsAbruptResumeType(const TNode<Smi> resume_type) {
1121cb0ef41Sopenharmony_ci    return SmiNotEqual(resume_type, SmiConstant(JSGeneratorObject::kNext));
1131cb0ef41Sopenharmony_ci  }
1141cb0ef41Sopenharmony_ci
1151cb0ef41Sopenharmony_ci  void AsyncGeneratorEnqueue(CodeStubArguments* args, TNode<Context> context,
1161cb0ef41Sopenharmony_ci                             TNode<Object> receiver, TNode<Object> value,
1171cb0ef41Sopenharmony_ci                             JSAsyncGeneratorObject::ResumeMode resume_mode,
1181cb0ef41Sopenharmony_ci                             const char* method_name);
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_ci  TNode<AsyncGeneratorRequest> TakeFirstAsyncGeneratorRequestFromQueue(
1211cb0ef41Sopenharmony_ci      TNode<JSAsyncGeneratorObject> generator);
1221cb0ef41Sopenharmony_ci  void AddAsyncGeneratorRequestToQueue(TNode<JSAsyncGeneratorObject> generator,
1231cb0ef41Sopenharmony_ci                                       TNode<AsyncGeneratorRequest> request);
1241cb0ef41Sopenharmony_ci
1251cb0ef41Sopenharmony_ci  TNode<AsyncGeneratorRequest> AllocateAsyncGeneratorRequest(
1261cb0ef41Sopenharmony_ci      JSAsyncGeneratorObject::ResumeMode resume_mode,
1271cb0ef41Sopenharmony_ci      TNode<Object> resume_value, TNode<JSPromise> promise);
1281cb0ef41Sopenharmony_ci
1291cb0ef41Sopenharmony_ci  // Shared implementation of the catchable and uncatchable variations of Await
1301cb0ef41Sopenharmony_ci  // for AsyncGenerators.
1311cb0ef41Sopenharmony_ci  template <typename Descriptor>
1321cb0ef41Sopenharmony_ci  void AsyncGeneratorAwait(bool is_catchable);
1331cb0ef41Sopenharmony_ci  void AsyncGeneratorAwaitResumeClosure(
1341cb0ef41Sopenharmony_ci      TNode<Context> context, TNode<Object> value,
1351cb0ef41Sopenharmony_ci      JSAsyncGeneratorObject::ResumeMode resume_mode);
1361cb0ef41Sopenharmony_ci};
1371cb0ef41Sopenharmony_ci
1381cb0ef41Sopenharmony_ci// Shared implementation for the 3 Async Iterator protocol methods of Async
1391cb0ef41Sopenharmony_ci// Generators.
1401cb0ef41Sopenharmony_civoid AsyncGeneratorBuiltinsAssembler::AsyncGeneratorEnqueue(
1411cb0ef41Sopenharmony_ci    CodeStubArguments* args, TNode<Context> context, TNode<Object> receiver,
1421cb0ef41Sopenharmony_ci    TNode<Object> value, JSAsyncGeneratorObject::ResumeMode resume_mode,
1431cb0ef41Sopenharmony_ci    const char* method_name) {
1441cb0ef41Sopenharmony_ci  // AsyncGeneratorEnqueue produces a new Promise, and appends it to the list
1451cb0ef41Sopenharmony_ci  // of async generator requests to be executed. If the generator is not
1461cb0ef41Sopenharmony_ci  // presently executing, then this method will loop through, processing each
1471cb0ef41Sopenharmony_ci  // request from front to back.
1481cb0ef41Sopenharmony_ci  // This loop resides in AsyncGeneratorResumeNext.
1491cb0ef41Sopenharmony_ci  TNode<JSPromise> promise = NewJSPromise(context);
1501cb0ef41Sopenharmony_ci
1511cb0ef41Sopenharmony_ci  Label if_receiverisincompatible(this, Label::kDeferred);
1521cb0ef41Sopenharmony_ci  GotoIf(TaggedIsSmi(receiver), &if_receiverisincompatible);
1531cb0ef41Sopenharmony_ci  GotoIfNot(HasInstanceType(CAST(receiver), JS_ASYNC_GENERATOR_OBJECT_TYPE),
1541cb0ef41Sopenharmony_ci            &if_receiverisincompatible);
1551cb0ef41Sopenharmony_ci
1561cb0ef41Sopenharmony_ci  {
1571cb0ef41Sopenharmony_ci    Label done(this);
1581cb0ef41Sopenharmony_ci    const TNode<JSAsyncGeneratorObject> generator = CAST(receiver);
1591cb0ef41Sopenharmony_ci    const TNode<AsyncGeneratorRequest> req =
1601cb0ef41Sopenharmony_ci        AllocateAsyncGeneratorRequest(resume_mode, value, promise);
1611cb0ef41Sopenharmony_ci
1621cb0ef41Sopenharmony_ci    AddAsyncGeneratorRequestToQueue(generator, req);
1631cb0ef41Sopenharmony_ci
1641cb0ef41Sopenharmony_ci    // Let state be generator.[[AsyncGeneratorState]]
1651cb0ef41Sopenharmony_ci    // If state is not "executing", then
1661cb0ef41Sopenharmony_ci    //     Perform AsyncGeneratorResumeNext(Generator)
1671cb0ef41Sopenharmony_ci    // Check if the {receiver} is running or already closed.
1681cb0ef41Sopenharmony_ci    TNode<Smi> continuation = LoadGeneratorState(generator);
1691cb0ef41Sopenharmony_ci
1701cb0ef41Sopenharmony_ci    GotoIf(SmiEqual(continuation,
1711cb0ef41Sopenharmony_ci                    SmiConstant(JSAsyncGeneratorObject::kGeneratorExecuting)),
1721cb0ef41Sopenharmony_ci           &done);
1731cb0ef41Sopenharmony_ci
1741cb0ef41Sopenharmony_ci    CallBuiltin(Builtin::kAsyncGeneratorResumeNext, context, generator);
1751cb0ef41Sopenharmony_ci
1761cb0ef41Sopenharmony_ci    Goto(&done);
1771cb0ef41Sopenharmony_ci    BIND(&done);
1781cb0ef41Sopenharmony_ci    args->PopAndReturn(promise);
1791cb0ef41Sopenharmony_ci  }
1801cb0ef41Sopenharmony_ci
1811cb0ef41Sopenharmony_ci  BIND(&if_receiverisincompatible);
1821cb0ef41Sopenharmony_ci  {
1831cb0ef41Sopenharmony_ci    CallBuiltin(Builtin::kRejectPromise, context, promise,
1841cb0ef41Sopenharmony_ci                MakeTypeError(MessageTemplate::kIncompatibleMethodReceiver,
1851cb0ef41Sopenharmony_ci                              context, StringConstant(method_name), receiver),
1861cb0ef41Sopenharmony_ci                TrueConstant());
1871cb0ef41Sopenharmony_ci    args->PopAndReturn(promise);
1881cb0ef41Sopenharmony_ci  }
1891cb0ef41Sopenharmony_ci}
1901cb0ef41Sopenharmony_ci
1911cb0ef41Sopenharmony_ciTNode<AsyncGeneratorRequest>
1921cb0ef41Sopenharmony_ciAsyncGeneratorBuiltinsAssembler::AllocateAsyncGeneratorRequest(
1931cb0ef41Sopenharmony_ci    JSAsyncGeneratorObject::ResumeMode resume_mode, TNode<Object> resume_value,
1941cb0ef41Sopenharmony_ci    TNode<JSPromise> promise) {
1951cb0ef41Sopenharmony_ci  TNode<HeapObject> request = Allocate(AsyncGeneratorRequest::kSize);
1961cb0ef41Sopenharmony_ci  StoreMapNoWriteBarrier(request, RootIndex::kAsyncGeneratorRequestMap);
1971cb0ef41Sopenharmony_ci  StoreObjectFieldNoWriteBarrier(request, AsyncGeneratorRequest::kNextOffset,
1981cb0ef41Sopenharmony_ci                                 UndefinedConstant());
1991cb0ef41Sopenharmony_ci  StoreObjectFieldNoWriteBarrier(request,
2001cb0ef41Sopenharmony_ci                                 AsyncGeneratorRequest::kResumeModeOffset,
2011cb0ef41Sopenharmony_ci                                 SmiConstant(resume_mode));
2021cb0ef41Sopenharmony_ci  StoreObjectFieldNoWriteBarrier(request, AsyncGeneratorRequest::kValueOffset,
2031cb0ef41Sopenharmony_ci                                 resume_value);
2041cb0ef41Sopenharmony_ci  StoreObjectFieldNoWriteBarrier(request, AsyncGeneratorRequest::kPromiseOffset,
2051cb0ef41Sopenharmony_ci                                 promise);
2061cb0ef41Sopenharmony_ci  StoreObjectFieldRoot(request, AsyncGeneratorRequest::kNextOffset,
2071cb0ef41Sopenharmony_ci                       RootIndex::kUndefinedValue);
2081cb0ef41Sopenharmony_ci  return CAST(request);
2091cb0ef41Sopenharmony_ci}
2101cb0ef41Sopenharmony_ci
2111cb0ef41Sopenharmony_civoid AsyncGeneratorBuiltinsAssembler::AsyncGeneratorAwaitResumeClosure(
2121cb0ef41Sopenharmony_ci    TNode<Context> context, TNode<Object> value,
2131cb0ef41Sopenharmony_ci    JSAsyncGeneratorObject::ResumeMode resume_mode) {
2141cb0ef41Sopenharmony_ci  const TNode<JSAsyncGeneratorObject> async_generator_object =
2151cb0ef41Sopenharmony_ci      CAST(LoadContextElement(context, Context::EXTENSION_INDEX));
2161cb0ef41Sopenharmony_ci
2171cb0ef41Sopenharmony_ci  SetGeneratorNotAwaiting(async_generator_object);
2181cb0ef41Sopenharmony_ci
2191cb0ef41Sopenharmony_ci  CSA_SLOW_DCHECK(this, IsGeneratorSuspended(async_generator_object));
2201cb0ef41Sopenharmony_ci
2211cb0ef41Sopenharmony_ci  // Remember the {resume_mode} for the {async_generator_object}.
2221cb0ef41Sopenharmony_ci  StoreObjectFieldNoWriteBarrier(async_generator_object,
2231cb0ef41Sopenharmony_ci                                 JSGeneratorObject::kResumeModeOffset,
2241cb0ef41Sopenharmony_ci                                 SmiConstant(resume_mode));
2251cb0ef41Sopenharmony_ci
2261cb0ef41Sopenharmony_ci  // Push the promise for the {async_generator_object} back onto the catch
2271cb0ef41Sopenharmony_ci  // prediction stack to handle exceptions thrown after resuming from the
2281cb0ef41Sopenharmony_ci  // await properly.
2291cb0ef41Sopenharmony_ci  Label if_instrumentation(this, Label::kDeferred),
2301cb0ef41Sopenharmony_ci      if_instrumentation_done(this);
2311cb0ef41Sopenharmony_ci  Branch(IsDebugActive(), &if_instrumentation, &if_instrumentation_done);
2321cb0ef41Sopenharmony_ci  BIND(&if_instrumentation);
2331cb0ef41Sopenharmony_ci  {
2341cb0ef41Sopenharmony_ci    TNode<AsyncGeneratorRequest> request =
2351cb0ef41Sopenharmony_ci        CAST(LoadFirstAsyncGeneratorRequestFromQueue(async_generator_object));
2361cb0ef41Sopenharmony_ci    TNode<JSPromise> promise = LoadObjectField<JSPromise>(
2371cb0ef41Sopenharmony_ci        request, AsyncGeneratorRequest::kPromiseOffset);
2381cb0ef41Sopenharmony_ci    CallRuntime(Runtime::kDebugPushPromise, context, promise);
2391cb0ef41Sopenharmony_ci    Goto(&if_instrumentation_done);
2401cb0ef41Sopenharmony_ci  }
2411cb0ef41Sopenharmony_ci  BIND(&if_instrumentation_done);
2421cb0ef41Sopenharmony_ci
2431cb0ef41Sopenharmony_ci  CallStub(CodeFactory::ResumeGenerator(isolate()), context, value,
2441cb0ef41Sopenharmony_ci           async_generator_object);
2451cb0ef41Sopenharmony_ci
2461cb0ef41Sopenharmony_ci  TailCallBuiltin(Builtin::kAsyncGeneratorResumeNext, context,
2471cb0ef41Sopenharmony_ci                  async_generator_object);
2481cb0ef41Sopenharmony_ci}
2491cb0ef41Sopenharmony_ci
2501cb0ef41Sopenharmony_citemplate <typename Descriptor>
2511cb0ef41Sopenharmony_civoid AsyncGeneratorBuiltinsAssembler::AsyncGeneratorAwait(bool is_catchable) {
2521cb0ef41Sopenharmony_ci  auto async_generator_object =
2531cb0ef41Sopenharmony_ci      Parameter<JSAsyncGeneratorObject>(Descriptor::kAsyncGeneratorObject);
2541cb0ef41Sopenharmony_ci  auto value = Parameter<Object>(Descriptor::kValue);
2551cb0ef41Sopenharmony_ci  auto context = Parameter<Context>(Descriptor::kContext);
2561cb0ef41Sopenharmony_ci
2571cb0ef41Sopenharmony_ci  TNode<AsyncGeneratorRequest> request =
2581cb0ef41Sopenharmony_ci      CAST(LoadFirstAsyncGeneratorRequestFromQueue(async_generator_object));
2591cb0ef41Sopenharmony_ci  TNode<JSPromise> outer_promise = LoadObjectField<JSPromise>(
2601cb0ef41Sopenharmony_ci      request, AsyncGeneratorRequest::kPromiseOffset);
2611cb0ef41Sopenharmony_ci
2621cb0ef41Sopenharmony_ci  Await(context, async_generator_object, value, outer_promise,
2631cb0ef41Sopenharmony_ci        AsyncGeneratorAwaitResolveSharedFunConstant(),
2641cb0ef41Sopenharmony_ci        AsyncGeneratorAwaitRejectSharedFunConstant(), is_catchable);
2651cb0ef41Sopenharmony_ci  SetGeneratorAwaiting(async_generator_object);
2661cb0ef41Sopenharmony_ci  Return(UndefinedConstant());
2671cb0ef41Sopenharmony_ci}
2681cb0ef41Sopenharmony_ci
2691cb0ef41Sopenharmony_civoid AsyncGeneratorBuiltinsAssembler::AddAsyncGeneratorRequestToQueue(
2701cb0ef41Sopenharmony_ci    TNode<JSAsyncGeneratorObject> generator,
2711cb0ef41Sopenharmony_ci    TNode<AsyncGeneratorRequest> request) {
2721cb0ef41Sopenharmony_ci  TVARIABLE(HeapObject, var_current);
2731cb0ef41Sopenharmony_ci  Label empty(this), loop(this, &var_current), done(this);
2741cb0ef41Sopenharmony_ci
2751cb0ef41Sopenharmony_ci  var_current = LoadObjectField<HeapObject>(
2761cb0ef41Sopenharmony_ci      generator, JSAsyncGeneratorObject::kQueueOffset);
2771cb0ef41Sopenharmony_ci  Branch(IsUndefined(var_current.value()), &empty, &loop);
2781cb0ef41Sopenharmony_ci
2791cb0ef41Sopenharmony_ci  BIND(&empty);
2801cb0ef41Sopenharmony_ci  {
2811cb0ef41Sopenharmony_ci    StoreObjectField(generator, JSAsyncGeneratorObject::kQueueOffset, request);
2821cb0ef41Sopenharmony_ci    Goto(&done);
2831cb0ef41Sopenharmony_ci  }
2841cb0ef41Sopenharmony_ci
2851cb0ef41Sopenharmony_ci  BIND(&loop);
2861cb0ef41Sopenharmony_ci  {
2871cb0ef41Sopenharmony_ci    Label loop_next(this), next_empty(this);
2881cb0ef41Sopenharmony_ci    TNode<AsyncGeneratorRequest> current = CAST(var_current.value());
2891cb0ef41Sopenharmony_ci    TNode<HeapObject> next = LoadObjectField<HeapObject>(
2901cb0ef41Sopenharmony_ci        current, AsyncGeneratorRequest::kNextOffset);
2911cb0ef41Sopenharmony_ci
2921cb0ef41Sopenharmony_ci    Branch(IsUndefined(next), &next_empty, &loop_next);
2931cb0ef41Sopenharmony_ci    BIND(&next_empty);
2941cb0ef41Sopenharmony_ci    {
2951cb0ef41Sopenharmony_ci      StoreObjectField(current, AsyncGeneratorRequest::kNextOffset, request);
2961cb0ef41Sopenharmony_ci      Goto(&done);
2971cb0ef41Sopenharmony_ci    }
2981cb0ef41Sopenharmony_ci
2991cb0ef41Sopenharmony_ci    BIND(&loop_next);
3001cb0ef41Sopenharmony_ci    {
3011cb0ef41Sopenharmony_ci      var_current = next;
3021cb0ef41Sopenharmony_ci      Goto(&loop);
3031cb0ef41Sopenharmony_ci    }
3041cb0ef41Sopenharmony_ci  }
3051cb0ef41Sopenharmony_ci  BIND(&done);
3061cb0ef41Sopenharmony_ci}
3071cb0ef41Sopenharmony_ci
3081cb0ef41Sopenharmony_ciTNode<AsyncGeneratorRequest>
3091cb0ef41Sopenharmony_ciAsyncGeneratorBuiltinsAssembler::TakeFirstAsyncGeneratorRequestFromQueue(
3101cb0ef41Sopenharmony_ci    TNode<JSAsyncGeneratorObject> generator) {
3111cb0ef41Sopenharmony_ci  // Removes and returns the first AsyncGeneratorRequest from a
3121cb0ef41Sopenharmony_ci  // JSAsyncGeneratorObject's queue. Asserts that the queue is not empty.
3131cb0ef41Sopenharmony_ci  TNode<AsyncGeneratorRequest> request = LoadObjectField<AsyncGeneratorRequest>(
3141cb0ef41Sopenharmony_ci      generator, JSAsyncGeneratorObject::kQueueOffset);
3151cb0ef41Sopenharmony_ci
3161cb0ef41Sopenharmony_ci  TNode<Object> next =
3171cb0ef41Sopenharmony_ci      LoadObjectField(request, AsyncGeneratorRequest::kNextOffset);
3181cb0ef41Sopenharmony_ci
3191cb0ef41Sopenharmony_ci  StoreObjectField(generator, JSAsyncGeneratorObject::kQueueOffset, next);
3201cb0ef41Sopenharmony_ci  return request;
3211cb0ef41Sopenharmony_ci}
3221cb0ef41Sopenharmony_ci}  // namespace
3231cb0ef41Sopenharmony_ci
3241cb0ef41Sopenharmony_ci// https://tc39.github.io/proposal-async-iteration/
3251cb0ef41Sopenharmony_ci// Section #sec-asyncgenerator-prototype-next
3261cb0ef41Sopenharmony_ciTF_BUILTIN(AsyncGeneratorPrototypeNext, AsyncGeneratorBuiltinsAssembler) {
3271cb0ef41Sopenharmony_ci  const int kValueArg = 0;
3281cb0ef41Sopenharmony_ci
3291cb0ef41Sopenharmony_ci  TNode<IntPtrT> argc = ChangeInt32ToIntPtr(
3301cb0ef41Sopenharmony_ci      UncheckedParameter<Int32T>(Descriptor::kJSActualArgumentsCount));
3311cb0ef41Sopenharmony_ci  CodeStubArguments args(this, argc);
3321cb0ef41Sopenharmony_ci
3331cb0ef41Sopenharmony_ci  TNode<Object> generator = args.GetReceiver();
3341cb0ef41Sopenharmony_ci  TNode<Object> value = args.GetOptionalArgumentValue(kValueArg);
3351cb0ef41Sopenharmony_ci  auto context = Parameter<Context>(Descriptor::kContext);
3361cb0ef41Sopenharmony_ci
3371cb0ef41Sopenharmony_ci  AsyncGeneratorEnqueue(&args, context, generator, value,
3381cb0ef41Sopenharmony_ci                        JSAsyncGeneratorObject::kNext,
3391cb0ef41Sopenharmony_ci                        "[AsyncGenerator].prototype.next");
3401cb0ef41Sopenharmony_ci}
3411cb0ef41Sopenharmony_ci
3421cb0ef41Sopenharmony_ci// https://tc39.github.io/proposal-async-iteration/
3431cb0ef41Sopenharmony_ci// Section #sec-asyncgenerator-prototype-return
3441cb0ef41Sopenharmony_ciTF_BUILTIN(AsyncGeneratorPrototypeReturn, AsyncGeneratorBuiltinsAssembler) {
3451cb0ef41Sopenharmony_ci  const int kValueArg = 0;
3461cb0ef41Sopenharmony_ci
3471cb0ef41Sopenharmony_ci  TNode<IntPtrT> argc = ChangeInt32ToIntPtr(
3481cb0ef41Sopenharmony_ci      UncheckedParameter<Int32T>(Descriptor::kJSActualArgumentsCount));
3491cb0ef41Sopenharmony_ci  CodeStubArguments args(this, argc);
3501cb0ef41Sopenharmony_ci
3511cb0ef41Sopenharmony_ci  TNode<Object> generator = args.GetReceiver();
3521cb0ef41Sopenharmony_ci  TNode<Object> value = args.GetOptionalArgumentValue(kValueArg);
3531cb0ef41Sopenharmony_ci  auto context = Parameter<Context>(Descriptor::kContext);
3541cb0ef41Sopenharmony_ci
3551cb0ef41Sopenharmony_ci  AsyncGeneratorEnqueue(&args, context, generator, value,
3561cb0ef41Sopenharmony_ci                        JSAsyncGeneratorObject::kReturn,
3571cb0ef41Sopenharmony_ci                        "[AsyncGenerator].prototype.return");
3581cb0ef41Sopenharmony_ci}
3591cb0ef41Sopenharmony_ci
3601cb0ef41Sopenharmony_ci// https://tc39.github.io/proposal-async-iteration/
3611cb0ef41Sopenharmony_ci// Section #sec-asyncgenerator-prototype-throw
3621cb0ef41Sopenharmony_ciTF_BUILTIN(AsyncGeneratorPrototypeThrow, AsyncGeneratorBuiltinsAssembler) {
3631cb0ef41Sopenharmony_ci  const int kValueArg = 0;
3641cb0ef41Sopenharmony_ci
3651cb0ef41Sopenharmony_ci  TNode<IntPtrT> argc = ChangeInt32ToIntPtr(
3661cb0ef41Sopenharmony_ci      UncheckedParameter<Int32T>(Descriptor::kJSActualArgumentsCount));
3671cb0ef41Sopenharmony_ci  CodeStubArguments args(this, argc);
3681cb0ef41Sopenharmony_ci
3691cb0ef41Sopenharmony_ci  TNode<Object> generator = args.GetReceiver();
3701cb0ef41Sopenharmony_ci  TNode<Object> value = args.GetOptionalArgumentValue(kValueArg);
3711cb0ef41Sopenharmony_ci  auto context = Parameter<Context>(Descriptor::kContext);
3721cb0ef41Sopenharmony_ci
3731cb0ef41Sopenharmony_ci  AsyncGeneratorEnqueue(&args, context, generator, value,
3741cb0ef41Sopenharmony_ci                        JSAsyncGeneratorObject::kThrow,
3751cb0ef41Sopenharmony_ci                        "[AsyncGenerator].prototype.throw");
3761cb0ef41Sopenharmony_ci}
3771cb0ef41Sopenharmony_ci
3781cb0ef41Sopenharmony_ciTF_BUILTIN(AsyncGeneratorAwaitResolveClosure, AsyncGeneratorBuiltinsAssembler) {
3791cb0ef41Sopenharmony_ci  auto value = Parameter<Object>(Descriptor::kValue);
3801cb0ef41Sopenharmony_ci  auto context = Parameter<Context>(Descriptor::kContext);
3811cb0ef41Sopenharmony_ci  AsyncGeneratorAwaitResumeClosure(context, value,
3821cb0ef41Sopenharmony_ci                                   JSAsyncGeneratorObject::kNext);
3831cb0ef41Sopenharmony_ci}
3841cb0ef41Sopenharmony_ci
3851cb0ef41Sopenharmony_ciTF_BUILTIN(AsyncGeneratorAwaitRejectClosure, AsyncGeneratorBuiltinsAssembler) {
3861cb0ef41Sopenharmony_ci  auto value = Parameter<Object>(Descriptor::kValue);
3871cb0ef41Sopenharmony_ci  auto context = Parameter<Context>(Descriptor::kContext);
3881cb0ef41Sopenharmony_ci  AsyncGeneratorAwaitResumeClosure(context, value,
3891cb0ef41Sopenharmony_ci                                   JSAsyncGeneratorObject::kThrow);
3901cb0ef41Sopenharmony_ci}
3911cb0ef41Sopenharmony_ci
3921cb0ef41Sopenharmony_ciTF_BUILTIN(AsyncGeneratorAwaitUncaught, AsyncGeneratorBuiltinsAssembler) {
3931cb0ef41Sopenharmony_ci  const bool kIsCatchable = false;
3941cb0ef41Sopenharmony_ci  AsyncGeneratorAwait<Descriptor>(kIsCatchable);
3951cb0ef41Sopenharmony_ci}
3961cb0ef41Sopenharmony_ci
3971cb0ef41Sopenharmony_ciTF_BUILTIN(AsyncGeneratorAwaitCaught, AsyncGeneratorBuiltinsAssembler) {
3981cb0ef41Sopenharmony_ci  const bool kIsCatchable = true;
3991cb0ef41Sopenharmony_ci  AsyncGeneratorAwait<Descriptor>(kIsCatchable);
4001cb0ef41Sopenharmony_ci}
4011cb0ef41Sopenharmony_ci
4021cb0ef41Sopenharmony_ciTF_BUILTIN(AsyncGeneratorResumeNext, AsyncGeneratorBuiltinsAssembler) {
4031cb0ef41Sopenharmony_ci  const auto generator =
4041cb0ef41Sopenharmony_ci      Parameter<JSAsyncGeneratorObject>(Descriptor::kGenerator);
4051cb0ef41Sopenharmony_ci  const auto context = Parameter<Context>(Descriptor::kContext);
4061cb0ef41Sopenharmony_ci
4071cb0ef41Sopenharmony_ci  // The penultimate step of proposal-async-iteration/#sec-asyncgeneratorresolve
4081cb0ef41Sopenharmony_ci  // and proposal-async-iteration/#sec-asyncgeneratorreject both recursively
4091cb0ef41Sopenharmony_ci  // invoke AsyncGeneratorResumeNext() again.
4101cb0ef41Sopenharmony_ci  //
4111cb0ef41Sopenharmony_ci  // This implementation does not implement this recursively, but instead
4121cb0ef41Sopenharmony_ci  // performs a loop in AsyncGeneratorResumeNext, which  continues as long as
4131cb0ef41Sopenharmony_ci  // there is an AsyncGeneratorRequest in the queue, and as long as the
4141cb0ef41Sopenharmony_ci  // generator is not suspended due to an AwaitExpression.
4151cb0ef41Sopenharmony_ci  TVARIABLE(Smi, var_state, LoadGeneratorState(generator));
4161cb0ef41Sopenharmony_ci  TVARIABLE(HeapObject, var_next,
4171cb0ef41Sopenharmony_ci            LoadFirstAsyncGeneratorRequestFromQueue(generator));
4181cb0ef41Sopenharmony_ci  Label start(this, {&var_state, &var_next});
4191cb0ef41Sopenharmony_ci  Goto(&start);
4201cb0ef41Sopenharmony_ci  BIND(&start);
4211cb0ef41Sopenharmony_ci
4221cb0ef41Sopenharmony_ci  CSA_DCHECK(this, IsGeneratorNotExecuting(generator));
4231cb0ef41Sopenharmony_ci
4241cb0ef41Sopenharmony_ci  // Stop resuming if suspended for Await.
4251cb0ef41Sopenharmony_ci  ReturnIf(IsGeneratorAwaiting(generator), UndefinedConstant());
4261cb0ef41Sopenharmony_ci
4271cb0ef41Sopenharmony_ci  // Stop resuming if request queue is empty.
4281cb0ef41Sopenharmony_ci  ReturnIf(IsUndefined(var_next.value()), UndefinedConstant());
4291cb0ef41Sopenharmony_ci
4301cb0ef41Sopenharmony_ci  const TNode<AsyncGeneratorRequest> next = CAST(var_next.value());
4311cb0ef41Sopenharmony_ci  const TNode<Smi> resume_type = LoadResumeTypeFromAsyncGeneratorRequest(next);
4321cb0ef41Sopenharmony_ci
4331cb0ef41Sopenharmony_ci  Label if_abrupt(this), if_normal(this), resume_generator(this);
4341cb0ef41Sopenharmony_ci  Branch(IsAbruptResumeType(resume_type), &if_abrupt, &if_normal);
4351cb0ef41Sopenharmony_ci  BIND(&if_abrupt);
4361cb0ef41Sopenharmony_ci  {
4371cb0ef41Sopenharmony_ci    Label settle_promise(this), if_return(this), if_throw(this);
4381cb0ef41Sopenharmony_ci    GotoIfNot(IsGeneratorStateSuspendedAtStart(var_state.value()),
4391cb0ef41Sopenharmony_ci              &settle_promise);
4401cb0ef41Sopenharmony_ci    CloseGenerator(generator);
4411cb0ef41Sopenharmony_ci    var_state = SmiConstant(JSGeneratorObject::kGeneratorClosed);
4421cb0ef41Sopenharmony_ci    Goto(&settle_promise);
4431cb0ef41Sopenharmony_ci
4441cb0ef41Sopenharmony_ci    BIND(&settle_promise);
4451cb0ef41Sopenharmony_ci    TNode<Object> next_value = LoadValueFromAsyncGeneratorRequest(next);
4461cb0ef41Sopenharmony_ci    Branch(SmiEqual(resume_type, SmiConstant(JSGeneratorObject::kReturn)),
4471cb0ef41Sopenharmony_ci           &if_return, &if_throw);
4481cb0ef41Sopenharmony_ci
4491cb0ef41Sopenharmony_ci    BIND(&if_return);
4501cb0ef41Sopenharmony_ci    // For "return" completions, await the sent value. If the Await succeeds,
4511cb0ef41Sopenharmony_ci    // and the generator is not closed, resume the generator with a "return"
4521cb0ef41Sopenharmony_ci    // completion to allow `finally` blocks to be evaluated. Otherwise, perform
4531cb0ef41Sopenharmony_ci    // AsyncGeneratorResolve(awaitedValue, true). If the await fails and the
4541cb0ef41Sopenharmony_ci    // generator is not closed, resume the generator with a "throw" completion.
4551cb0ef41Sopenharmony_ci    // If the generator was closed, perform AsyncGeneratorReject(thrownValue).
4561cb0ef41Sopenharmony_ci    // In all cases, the last step is to call AsyncGeneratorResumeNext.
4571cb0ef41Sopenharmony_ci    TNode<Object> is_caught = CallRuntime(
4581cb0ef41Sopenharmony_ci        Runtime::kAsyncGeneratorHasCatchHandlerForPC, context, generator);
4591cb0ef41Sopenharmony_ci    TailCallBuiltin(Builtin::kAsyncGeneratorReturn, context, generator,
4601cb0ef41Sopenharmony_ci                    next_value, is_caught);
4611cb0ef41Sopenharmony_ci
4621cb0ef41Sopenharmony_ci    BIND(&if_throw);
4631cb0ef41Sopenharmony_ci    GotoIfNot(IsGeneratorStateClosed(var_state.value()), &resume_generator);
4641cb0ef41Sopenharmony_ci    CallBuiltin(Builtin::kAsyncGeneratorReject, context, generator, next_value);
4651cb0ef41Sopenharmony_ci    var_next = LoadFirstAsyncGeneratorRequestFromQueue(generator);
4661cb0ef41Sopenharmony_ci    Goto(&start);
4671cb0ef41Sopenharmony_ci  }
4681cb0ef41Sopenharmony_ci
4691cb0ef41Sopenharmony_ci  BIND(&if_normal);
4701cb0ef41Sopenharmony_ci  {
4711cb0ef41Sopenharmony_ci    GotoIfNot(IsGeneratorStateClosed(var_state.value()), &resume_generator);
4721cb0ef41Sopenharmony_ci    CallBuiltin(Builtin::kAsyncGeneratorResolve, context, generator,
4731cb0ef41Sopenharmony_ci                UndefinedConstant(), TrueConstant());
4741cb0ef41Sopenharmony_ci    var_state = LoadGeneratorState(generator);
4751cb0ef41Sopenharmony_ci    var_next = LoadFirstAsyncGeneratorRequestFromQueue(generator);
4761cb0ef41Sopenharmony_ci    Goto(&start);
4771cb0ef41Sopenharmony_ci  }
4781cb0ef41Sopenharmony_ci
4791cb0ef41Sopenharmony_ci  BIND(&resume_generator);
4801cb0ef41Sopenharmony_ci  {
4811cb0ef41Sopenharmony_ci    // Remember the {resume_type} for the {generator}.
4821cb0ef41Sopenharmony_ci    StoreObjectFieldNoWriteBarrier(
4831cb0ef41Sopenharmony_ci        generator, JSGeneratorObject::kResumeModeOffset, resume_type);
4841cb0ef41Sopenharmony_ci    CallStub(CodeFactory::ResumeGenerator(isolate()), context,
4851cb0ef41Sopenharmony_ci             LoadValueFromAsyncGeneratorRequest(next), generator);
4861cb0ef41Sopenharmony_ci    var_state = LoadGeneratorState(generator);
4871cb0ef41Sopenharmony_ci    var_next = LoadFirstAsyncGeneratorRequestFromQueue(generator);
4881cb0ef41Sopenharmony_ci    Goto(&start);
4891cb0ef41Sopenharmony_ci  }
4901cb0ef41Sopenharmony_ci}
4911cb0ef41Sopenharmony_ci
4921cb0ef41Sopenharmony_ciTF_BUILTIN(AsyncGeneratorResolve, AsyncGeneratorBuiltinsAssembler) {
4931cb0ef41Sopenharmony_ci  const auto generator =
4941cb0ef41Sopenharmony_ci      Parameter<JSAsyncGeneratorObject>(Descriptor::kGenerator);
4951cb0ef41Sopenharmony_ci  const auto value = Parameter<Object>(Descriptor::kValue);
4961cb0ef41Sopenharmony_ci  const auto done = Parameter<Object>(Descriptor::kDone);
4971cb0ef41Sopenharmony_ci  const auto context = Parameter<Context>(Descriptor::kContext);
4981cb0ef41Sopenharmony_ci
4991cb0ef41Sopenharmony_ci  CSA_DCHECK(this, Word32BinaryNot(IsGeneratorAwaiting(generator)));
5001cb0ef41Sopenharmony_ci
5011cb0ef41Sopenharmony_ci  // This operation should be called only when the `value` parameter has been
5021cb0ef41Sopenharmony_ci  // Await-ed. Typically, this means `value` is not a JSPromise value. However,
5031cb0ef41Sopenharmony_ci  // it may be a JSPromise value whose "then" method has been overridden to a
5041cb0ef41Sopenharmony_ci  // non-callable value. This can't be checked with assertions due to being
5051cb0ef41Sopenharmony_ci  // observable, but keep it in mind.
5061cb0ef41Sopenharmony_ci
5071cb0ef41Sopenharmony_ci  const TNode<AsyncGeneratorRequest> next =
5081cb0ef41Sopenharmony_ci      TakeFirstAsyncGeneratorRequestFromQueue(generator);
5091cb0ef41Sopenharmony_ci  const TNode<JSPromise> promise = LoadPromiseFromAsyncGeneratorRequest(next);
5101cb0ef41Sopenharmony_ci
5111cb0ef41Sopenharmony_ci  // Let iteratorResult be CreateIterResultObject(value, done).
5121cb0ef41Sopenharmony_ci  const TNode<HeapObject> iter_result = Allocate(JSIteratorResult::kSize);
5131cb0ef41Sopenharmony_ci  {
5141cb0ef41Sopenharmony_ci    TNode<Map> map = CAST(LoadContextElement(
5151cb0ef41Sopenharmony_ci        LoadNativeContext(context), Context::ITERATOR_RESULT_MAP_INDEX));
5161cb0ef41Sopenharmony_ci    StoreMapNoWriteBarrier(iter_result, map);
5171cb0ef41Sopenharmony_ci    StoreObjectFieldRoot(iter_result, JSIteratorResult::kPropertiesOrHashOffset,
5181cb0ef41Sopenharmony_ci                         RootIndex::kEmptyFixedArray);
5191cb0ef41Sopenharmony_ci    StoreObjectFieldRoot(iter_result, JSIteratorResult::kElementsOffset,
5201cb0ef41Sopenharmony_ci                         RootIndex::kEmptyFixedArray);
5211cb0ef41Sopenharmony_ci    StoreObjectFieldNoWriteBarrier(iter_result, JSIteratorResult::kValueOffset,
5221cb0ef41Sopenharmony_ci                                   value);
5231cb0ef41Sopenharmony_ci    StoreObjectFieldNoWriteBarrier(iter_result, JSIteratorResult::kDoneOffset,
5241cb0ef41Sopenharmony_ci                                   done);
5251cb0ef41Sopenharmony_ci  }
5261cb0ef41Sopenharmony_ci
5271cb0ef41Sopenharmony_ci  // We know that {iter_result} itself doesn't have any "then" property (a
5281cb0ef41Sopenharmony_ci  // freshly allocated IterResultObject only has "value" and "done" properties)
5291cb0ef41Sopenharmony_ci  // and we also know that the [[Prototype]] of {iter_result} is the intrinsic
5301cb0ef41Sopenharmony_ci  // %ObjectPrototype%. So we can skip the [[Resolve]] logic here completely
5311cb0ef41Sopenharmony_ci  // and directly call into the FulfillPromise operation if we can prove
5321cb0ef41Sopenharmony_ci  // that the %ObjectPrototype% also doesn't have any "then" property. This
5331cb0ef41Sopenharmony_ci  // is guarded by the Promise#then() protector.
5341cb0ef41Sopenharmony_ci  // If the PromiseHooks are enabled, we cannot take the shortcut here, since
5351cb0ef41Sopenharmony_ci  // the "promiseResolve" hook would not be fired otherwise.
5361cb0ef41Sopenharmony_ci  Label if_fast(this), if_slow(this, Label::kDeferred), return_promise(this);
5371cb0ef41Sopenharmony_ci  GotoIfForceSlowPath(&if_slow);
5381cb0ef41Sopenharmony_ci  GotoIf(IsIsolatePromiseHookEnabledOrHasAsyncEventDelegate(), &if_slow);
5391cb0ef41Sopenharmony_ci  Branch(IsPromiseThenProtectorCellInvalid(), &if_slow, &if_fast);
5401cb0ef41Sopenharmony_ci
5411cb0ef41Sopenharmony_ci  BIND(&if_fast);
5421cb0ef41Sopenharmony_ci  {
5431cb0ef41Sopenharmony_ci    // Skip the "then" on {iter_result} and directly fulfill the {promise}
5441cb0ef41Sopenharmony_ci    // with the {iter_result}.
5451cb0ef41Sopenharmony_ci    CallBuiltin(Builtin::kFulfillPromise, context, promise, iter_result);
5461cb0ef41Sopenharmony_ci    Goto(&return_promise);
5471cb0ef41Sopenharmony_ci  }
5481cb0ef41Sopenharmony_ci
5491cb0ef41Sopenharmony_ci  BIND(&if_slow);
5501cb0ef41Sopenharmony_ci  {
5511cb0ef41Sopenharmony_ci    // Perform Call(promiseCapability.[[Resolve]], undefined, «iteratorResult»).
5521cb0ef41Sopenharmony_ci    CallBuiltin(Builtin::kResolvePromise, context, promise, iter_result);
5531cb0ef41Sopenharmony_ci    Goto(&return_promise);
5541cb0ef41Sopenharmony_ci  }
5551cb0ef41Sopenharmony_ci
5561cb0ef41Sopenharmony_ci  // Per spec, AsyncGeneratorResolve() returns undefined. However, for the
5571cb0ef41Sopenharmony_ci  // benefit of %TraceExit(), return the Promise.
5581cb0ef41Sopenharmony_ci  BIND(&return_promise);
5591cb0ef41Sopenharmony_ci  Return(promise);
5601cb0ef41Sopenharmony_ci}
5611cb0ef41Sopenharmony_ci
5621cb0ef41Sopenharmony_ciTF_BUILTIN(AsyncGeneratorReject, AsyncGeneratorBuiltinsAssembler) {
5631cb0ef41Sopenharmony_ci  const auto generator =
5641cb0ef41Sopenharmony_ci      Parameter<JSAsyncGeneratorObject>(Descriptor::kGenerator);
5651cb0ef41Sopenharmony_ci  const auto value = Parameter<Object>(Descriptor::kValue);
5661cb0ef41Sopenharmony_ci  const auto context = Parameter<Context>(Descriptor::kContext);
5671cb0ef41Sopenharmony_ci
5681cb0ef41Sopenharmony_ci  TNode<AsyncGeneratorRequest> next =
5691cb0ef41Sopenharmony_ci      TakeFirstAsyncGeneratorRequestFromQueue(generator);
5701cb0ef41Sopenharmony_ci  TNode<JSPromise> promise = LoadPromiseFromAsyncGeneratorRequest(next);
5711cb0ef41Sopenharmony_ci
5721cb0ef41Sopenharmony_ci  Return(CallBuiltin(Builtin::kRejectPromise, context, promise, value,
5731cb0ef41Sopenharmony_ci                     TrueConstant()));
5741cb0ef41Sopenharmony_ci}
5751cb0ef41Sopenharmony_ci
5761cb0ef41Sopenharmony_ciTF_BUILTIN(AsyncGeneratorYield, AsyncGeneratorBuiltinsAssembler) {
5771cb0ef41Sopenharmony_ci  const auto generator = Parameter<JSGeneratorObject>(Descriptor::kGenerator);
5781cb0ef41Sopenharmony_ci  const auto value = Parameter<Object>(Descriptor::kValue);
5791cb0ef41Sopenharmony_ci  const auto is_caught = Parameter<Oddball>(Descriptor::kIsCaught);
5801cb0ef41Sopenharmony_ci  const auto context = Parameter<Context>(Descriptor::kContext);
5811cb0ef41Sopenharmony_ci
5821cb0ef41Sopenharmony_ci  const TNode<AsyncGeneratorRequest> request =
5831cb0ef41Sopenharmony_ci      CAST(LoadFirstAsyncGeneratorRequestFromQueue(generator));
5841cb0ef41Sopenharmony_ci  const TNode<JSPromise> outer_promise =
5851cb0ef41Sopenharmony_ci      LoadPromiseFromAsyncGeneratorRequest(request);
5861cb0ef41Sopenharmony_ci
5871cb0ef41Sopenharmony_ci  Await(context, generator, value, outer_promise,
5881cb0ef41Sopenharmony_ci        AsyncGeneratorYieldResolveSharedFunConstant(),
5891cb0ef41Sopenharmony_ci        AsyncGeneratorAwaitRejectSharedFunConstant(), is_caught);
5901cb0ef41Sopenharmony_ci  SetGeneratorAwaiting(generator);
5911cb0ef41Sopenharmony_ci  Return(UndefinedConstant());
5921cb0ef41Sopenharmony_ci}
5931cb0ef41Sopenharmony_ci
5941cb0ef41Sopenharmony_ciTF_BUILTIN(AsyncGeneratorYieldResolveClosure, AsyncGeneratorBuiltinsAssembler) {
5951cb0ef41Sopenharmony_ci  const auto context = Parameter<Context>(Descriptor::kContext);
5961cb0ef41Sopenharmony_ci  const auto value = Parameter<Object>(Descriptor::kValue);
5971cb0ef41Sopenharmony_ci  const TNode<JSAsyncGeneratorObject> generator =
5981cb0ef41Sopenharmony_ci      CAST(LoadContextElement(context, Context::EXTENSION_INDEX));
5991cb0ef41Sopenharmony_ci
6001cb0ef41Sopenharmony_ci  SetGeneratorNotAwaiting(generator);
6011cb0ef41Sopenharmony_ci
6021cb0ef41Sopenharmony_ci  // Per proposal-async-iteration/#sec-asyncgeneratoryield step 9
6031cb0ef41Sopenharmony_ci  // Return ! AsyncGeneratorResolve(_F_.[[Generator]], _value_, *false*).
6041cb0ef41Sopenharmony_ci  CallBuiltin(Builtin::kAsyncGeneratorResolve, context, generator, value,
6051cb0ef41Sopenharmony_ci              FalseConstant());
6061cb0ef41Sopenharmony_ci
6071cb0ef41Sopenharmony_ci  TailCallBuiltin(Builtin::kAsyncGeneratorResumeNext, context, generator);
6081cb0ef41Sopenharmony_ci}
6091cb0ef41Sopenharmony_ci
6101cb0ef41Sopenharmony_ciTF_BUILTIN(AsyncGeneratorReturn, AsyncGeneratorBuiltinsAssembler) {
6111cb0ef41Sopenharmony_ci  // AsyncGeneratorReturn is called when resuming requests with "return" resume
6121cb0ef41Sopenharmony_ci  // modes. It is similar to AsyncGeneratorAwait(), but selects different
6131cb0ef41Sopenharmony_ci  // resolve/reject closures depending on whether or not the generator is marked
6141cb0ef41Sopenharmony_ci  // as closed.
6151cb0ef41Sopenharmony_ci  //
6161cb0ef41Sopenharmony_ci  // In particular, non-closed generators will resume the generator with either
6171cb0ef41Sopenharmony_ci  // "return" or "throw" resume modes, allowing finally blocks or catch blocks
6181cb0ef41Sopenharmony_ci  // to be evaluated, as if the `await` were performed within the body of the
6191cb0ef41Sopenharmony_ci  // generator. (per proposal-async-iteration/#sec-asyncgeneratoryield step 8.b)
6201cb0ef41Sopenharmony_ci  //
6211cb0ef41Sopenharmony_ci  // Closed generators do not resume the generator in the resolve/reject
6221cb0ef41Sopenharmony_ci  // closures, but instead simply perform AsyncGeneratorResolve or
6231cb0ef41Sopenharmony_ci  // AsyncGeneratorReject with the awaited value
6241cb0ef41Sopenharmony_ci  // (per proposal-async-iteration/#sec-asyncgeneratorresumenext step 10.b.i)
6251cb0ef41Sopenharmony_ci  //
6261cb0ef41Sopenharmony_ci  // In all cases, the final step is to jump back to AsyncGeneratorResumeNext.
6271cb0ef41Sopenharmony_ci  const auto generator = Parameter<JSGeneratorObject>(Descriptor::kGenerator);
6281cb0ef41Sopenharmony_ci  const auto value = Parameter<Object>(Descriptor::kValue);
6291cb0ef41Sopenharmony_ci  const auto is_caught = Parameter<Oddball>(Descriptor::kIsCaught);
6301cb0ef41Sopenharmony_ci  const TNode<AsyncGeneratorRequest> req =
6311cb0ef41Sopenharmony_ci      CAST(LoadFirstAsyncGeneratorRequestFromQueue(generator));
6321cb0ef41Sopenharmony_ci
6331cb0ef41Sopenharmony_ci  Label perform_await(this);
6341cb0ef41Sopenharmony_ci  TVARIABLE(SharedFunctionInfo, var_on_resolve,
6351cb0ef41Sopenharmony_ci            AsyncGeneratorReturnClosedResolveSharedFunConstant());
6361cb0ef41Sopenharmony_ci
6371cb0ef41Sopenharmony_ci  TVARIABLE(SharedFunctionInfo, var_on_reject,
6381cb0ef41Sopenharmony_ci            AsyncGeneratorReturnClosedRejectSharedFunConstant());
6391cb0ef41Sopenharmony_ci
6401cb0ef41Sopenharmony_ci  const TNode<Smi> state = LoadGeneratorState(generator);
6411cb0ef41Sopenharmony_ci  GotoIf(IsGeneratorStateClosed(state), &perform_await);
6421cb0ef41Sopenharmony_ci  var_on_resolve = AsyncGeneratorReturnResolveSharedFunConstant();
6431cb0ef41Sopenharmony_ci  var_on_reject = AsyncGeneratorAwaitRejectSharedFunConstant();
6441cb0ef41Sopenharmony_ci
6451cb0ef41Sopenharmony_ci  Goto(&perform_await);
6461cb0ef41Sopenharmony_ci
6471cb0ef41Sopenharmony_ci  BIND(&perform_await);
6481cb0ef41Sopenharmony_ci
6491cb0ef41Sopenharmony_ci  SetGeneratorAwaiting(generator);
6501cb0ef41Sopenharmony_ci  auto context = Parameter<Context>(Descriptor::kContext);
6511cb0ef41Sopenharmony_ci  const TNode<JSPromise> outer_promise =
6521cb0ef41Sopenharmony_ci      LoadPromiseFromAsyncGeneratorRequest(req);
6531cb0ef41Sopenharmony_ci  Await(context, generator, value, outer_promise, var_on_resolve.value(),
6541cb0ef41Sopenharmony_ci        var_on_reject.value(), is_caught);
6551cb0ef41Sopenharmony_ci
6561cb0ef41Sopenharmony_ci  Return(UndefinedConstant());
6571cb0ef41Sopenharmony_ci}
6581cb0ef41Sopenharmony_ci
6591cb0ef41Sopenharmony_ci// On-resolve closure for Await in AsyncGeneratorReturn
6601cb0ef41Sopenharmony_ci// Resume the generator with "return" resume_mode, and finally perform
6611cb0ef41Sopenharmony_ci// AsyncGeneratorResumeNext. Per
6621cb0ef41Sopenharmony_ci// proposal-async-iteration/#sec-asyncgeneratoryield step 8.e
6631cb0ef41Sopenharmony_ciTF_BUILTIN(AsyncGeneratorReturnResolveClosure,
6641cb0ef41Sopenharmony_ci           AsyncGeneratorBuiltinsAssembler) {
6651cb0ef41Sopenharmony_ci  const auto context = Parameter<Context>(Descriptor::kContext);
6661cb0ef41Sopenharmony_ci  const auto value = Parameter<Object>(Descriptor::kValue);
6671cb0ef41Sopenharmony_ci  AsyncGeneratorAwaitResumeClosure(context, value, JSGeneratorObject::kReturn);
6681cb0ef41Sopenharmony_ci}
6691cb0ef41Sopenharmony_ci
6701cb0ef41Sopenharmony_ci// On-resolve closure for Await in AsyncGeneratorReturn
6711cb0ef41Sopenharmony_ci// Perform AsyncGeneratorResolve({awaited_value}, true) and finally perform
6721cb0ef41Sopenharmony_ci// AsyncGeneratorResumeNext.
6731cb0ef41Sopenharmony_ciTF_BUILTIN(AsyncGeneratorReturnClosedResolveClosure,
6741cb0ef41Sopenharmony_ci           AsyncGeneratorBuiltinsAssembler) {
6751cb0ef41Sopenharmony_ci  const auto context = Parameter<Context>(Descriptor::kContext);
6761cb0ef41Sopenharmony_ci  const auto value = Parameter<Object>(Descriptor::kValue);
6771cb0ef41Sopenharmony_ci  const TNode<JSAsyncGeneratorObject> generator =
6781cb0ef41Sopenharmony_ci      CAST(LoadContextElement(context, Context::EXTENSION_INDEX));
6791cb0ef41Sopenharmony_ci
6801cb0ef41Sopenharmony_ci  SetGeneratorNotAwaiting(generator);
6811cb0ef41Sopenharmony_ci
6821cb0ef41Sopenharmony_ci  // https://tc39.github.io/proposal-async-iteration/
6831cb0ef41Sopenharmony_ci  //    #async-generator-resume-next-return-processor-fulfilled step 2:
6841cb0ef41Sopenharmony_ci  //  Return ! AsyncGeneratorResolve(_F_.[[Generator]], _value_, *true*).
6851cb0ef41Sopenharmony_ci  CallBuiltin(Builtin::kAsyncGeneratorResolve, context, generator, value,
6861cb0ef41Sopenharmony_ci              TrueConstant());
6871cb0ef41Sopenharmony_ci
6881cb0ef41Sopenharmony_ci  TailCallBuiltin(Builtin::kAsyncGeneratorResumeNext, context, generator);
6891cb0ef41Sopenharmony_ci}
6901cb0ef41Sopenharmony_ci
6911cb0ef41Sopenharmony_ciTF_BUILTIN(AsyncGeneratorReturnClosedRejectClosure,
6921cb0ef41Sopenharmony_ci           AsyncGeneratorBuiltinsAssembler) {
6931cb0ef41Sopenharmony_ci  const auto context = Parameter<Context>(Descriptor::kContext);
6941cb0ef41Sopenharmony_ci  const auto value = Parameter<Object>(Descriptor::kValue);
6951cb0ef41Sopenharmony_ci  const TNode<JSAsyncGeneratorObject> generator =
6961cb0ef41Sopenharmony_ci      CAST(LoadContextElement(context, Context::EXTENSION_INDEX));
6971cb0ef41Sopenharmony_ci
6981cb0ef41Sopenharmony_ci  SetGeneratorNotAwaiting(generator);
6991cb0ef41Sopenharmony_ci
7001cb0ef41Sopenharmony_ci  // https://tc39.github.io/proposal-async-iteration/
7011cb0ef41Sopenharmony_ci  //    #async-generator-resume-next-return-processor-rejected step 2:
7021cb0ef41Sopenharmony_ci  // Return ! AsyncGeneratorReject(_F_.[[Generator]], _reason_).
7031cb0ef41Sopenharmony_ci  CallBuiltin(Builtin::kAsyncGeneratorReject, context, generator, value);
7041cb0ef41Sopenharmony_ci
7051cb0ef41Sopenharmony_ci  TailCallBuiltin(Builtin::kAsyncGeneratorResumeNext, context, generator);
7061cb0ef41Sopenharmony_ci}
7071cb0ef41Sopenharmony_ci
7081cb0ef41Sopenharmony_ci}  // namespace internal
7091cb0ef41Sopenharmony_ci}  // namespace v8
710