// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/builtins/builtins-async-gen.h"
#include "src/builtins/builtins-utils-gen.h"
#include "src/builtins/builtins.h"
#include "src/code-factory.h"
#include "src/code-stub-assembler.h"
#include "src/frames-inl.h"

namespace v8 {
namespace internal {

using compiler::Node;

namespace {

// Describe fields of Context associated with AsyncGeneratorAwait resume
// closures.
class AwaitContext {
 public:
  enum Fields { kGeneratorSlot = Context::MIN_CONTEXT_SLOTS, kLength };
};

class AsyncGeneratorBuiltinsAssembler : public AsyncBuiltinsAssembler {
 public:
  explicit AsyncGeneratorBuiltinsAssembler(CodeAssemblerState* state)
      : AsyncBuiltinsAssembler(state) {}

  inline Node* TaggedIsAsyncGenerator(Node* tagged_object) {
    Node* if_notsmi = TaggedIsNotSmi(tagged_object);
    return Select(if_notsmi,
                  [=]() {
                    return HasInstanceType(tagged_object,
                                           JS_ASYNC_GENERATOR_OBJECT_TYPE);
                  },
                  [=]() { return if_notsmi; }, MachineRepresentation::kBit);
  }
  inline Node* LoadGeneratorState(Node* const generator) {
    return LoadObjectField(generator, JSGeneratorObject::kContinuationOffset);
  }

  inline Node* IsGeneratorStateClosed(Node* const state) {
    return SmiEqual(state, SmiConstant(JSGeneratorObject::kGeneratorClosed));
  }
  inline Node* IsGeneratorClosed(Node* const generator) {
    return IsGeneratorStateClosed(LoadGeneratorState(generator));
  }

  inline Node* IsGeneratorStateSuspended(Node* const state) {
    return SmiGreaterThanOrEqual(state, SmiConstant(0));
  }

  inline Node* IsGeneratorSuspended(Node* const generator) {
    return IsGeneratorStateSuspended(LoadGeneratorState(generator));
  }

  inline Node* IsGeneratorStateSuspendedAtStart(Node* const state) {
    return SmiEqual(state, SmiConstant(0));
  }

  inline Node* IsGeneratorStateNotExecuting(Node* const state) {
    return SmiNotEqual(state,
                       SmiConstant(JSGeneratorObject::kGeneratorExecuting));
  }
  inline Node* IsGeneratorNotExecuting(Node* const generator) {
    return IsGeneratorStateNotExecuting(LoadGeneratorState(generator));
  }

  inline Node* LoadGeneratorAwaitedPromise(Node* const generator) {
    return LoadObjectField(generator,
                           JSAsyncGeneratorObject::kAwaitedPromiseOffset);
  }

  inline Node* IsGeneratorNotSuspendedForAwait(Node* const generator) {
    return IsUndefined(LoadGeneratorAwaitedPromise(generator));
  }

  inline Node* IsGeneratorSuspendedForAwait(Node* const generator) {
    return HasInstanceType(LoadGeneratorAwaitedPromise(generator),
                           JS_PROMISE_TYPE);
  }

  inline void ClearAwaitedPromise(Node* const generator) {
    StoreObjectFieldRoot(generator,
                         JSAsyncGeneratorObject::kAwaitedPromiseOffset,
                         Heap::kUndefinedValueRootIndex);
  }

  inline void CloseGenerator(Node* const generator) {
    StoreObjectFieldNoWriteBarrier(
        generator, JSGeneratorObject::kContinuationOffset,
        SmiConstant(JSGeneratorObject::kGeneratorClosed));
  }

  inline Node* IsFastJSIterResult(Node* const value, Node* const context) {
    CSA_ASSERT(this, TaggedIsNotSmi(value));
    Node* const native_context = LoadNativeContext(context);
    return WordEqual(
        LoadMap(value),
        LoadContextElement(native_context, Context::ITERATOR_RESULT_MAP_INDEX));
  }

  inline Node* LoadFirstAsyncGeneratorRequestFromQueue(Node* const generator) {
    return LoadObjectField(generator, JSAsyncGeneratorObject::kQueueOffset);
  }

  inline Node* LoadResumeTypeFromAsyncGeneratorRequest(Node* const request) {
    return LoadObjectField(request, AsyncGeneratorRequest::kResumeModeOffset);
  }

  inline Node* LoadPromiseFromAsyncGeneratorRequest(Node* const request) {
    return LoadObjectField(request, AsyncGeneratorRequest::kPromiseOffset);
  }

  inline Node* LoadValueFromAsyncGeneratorRequest(Node* const request) {
    return LoadObjectField(request, AsyncGeneratorRequest::kValueOffset);
  }

  inline Node* IsAbruptResumeType(Node* const resume_type) {
    return SmiNotEqual(resume_type, SmiConstant(JSGeneratorObject::kNext));
  }

  void AsyncGeneratorEnqueue(CodeStubArguments* args, Node* context,
                             Node* generator, Node* value,
                             JSAsyncGeneratorObject::ResumeMode resume_mode,
                             const char* method_name);

  Node* TakeFirstAsyncGeneratorRequestFromQueue(Node* generator);
  Node* TakeFirstAsyncGeneratorRequestFromQueueIfPresent(Node* generator,
                                                         Label* if_not_present);
  void AddAsyncGeneratorRequestToQueue(Node* generator, Node* request);

  Node* AllocateAsyncGeneratorRequest(
      JSAsyncGeneratorObject::ResumeMode resume_mode, Node* resume_value,
      Node* promise);

  // Shared implementation of the catchable and uncatchable variations of Await
  // for AsyncGenerators.
  template <typename Descriptor>
  void AsyncGeneratorAwait(bool is_catchable);
  void AsyncGeneratorAwaitResumeClosure(
      Node* context, Node* value,
      JSAsyncGeneratorObject::ResumeMode resume_mode);
};

// Shared implementation for the 3 Async Iterator protocol methods of Async
// Generators.
void AsyncGeneratorBuiltinsAssembler::AsyncGeneratorEnqueue(
    CodeStubArguments* args, Node* context, Node* generator, Node* value,
    JSAsyncGeneratorObject::ResumeMode resume_mode, const char* method_name) {
  // AsyncGeneratorEnqueue produces a new Promise, and appends it to the list
  // of async generator requests to be executed. If the generator is not
  // presently executing, then this method will loop through, processing each
  // request from front to back.
  // This loop resides in AsyncGeneratorResumeNext.
  Node* promise = AllocateAndInitJSPromise(context);

  Label enqueue(this), if_receiverisincompatible(this, Label::kDeferred);

  Branch(TaggedIsAsyncGenerator(generator), &enqueue,
         &if_receiverisincompatible);

  BIND(&enqueue);
  {
    Label done(this);
    Node* const req =
        AllocateAsyncGeneratorRequest(resume_mode, value, promise);

    AddAsyncGeneratorRequestToQueue(generator, req);

    // Let state be generator.[[AsyncGeneratorState]]
    // If state is not "executing", then
    //     Perform AsyncGeneratorResumeNext(Generator)
    // Check if the {receiver} is running or already closed.
    Node* continuation = LoadGeneratorState(generator);

    GotoIf(SmiEqual(continuation,
                    SmiConstant(JSAsyncGeneratorObject::kGeneratorExecuting)),
           &done);

    CallBuiltin(Builtins::kAsyncGeneratorResumeNext, context, generator);

    Goto(&done);
    BIND(&done);
    args->PopAndReturn(promise);
  }

  BIND(&if_receiverisincompatible);
  {
    Node* const error =
        MakeTypeError(MessageTemplate::kIncompatibleMethodReceiver, context,
                      StringConstant(method_name), generator);

    CallBuiltin(Builtins::kRejectNativePromise, context, promise, error,
                TrueConstant());
    args->PopAndReturn(promise);
  }
}

Node* AsyncGeneratorBuiltinsAssembler::AllocateAsyncGeneratorRequest(
    JSAsyncGeneratorObject::ResumeMode resume_mode, Node* resume_value,
    Node* promise) {
  CSA_SLOW_ASSERT(this, HasInstanceType(promise, JS_PROMISE_TYPE));
  Node* request = Allocate(AsyncGeneratorRequest::kSize);
  StoreMapNoWriteBarrier(request, Heap::kAsyncGeneratorRequestMapRootIndex);
  StoreObjectFieldNoWriteBarrier(request, AsyncGeneratorRequest::kNextOffset,
                                 UndefinedConstant());
  StoreObjectFieldNoWriteBarrier(request,
                                 AsyncGeneratorRequest::kResumeModeOffset,
                                 SmiConstant(resume_mode));
  StoreObjectFieldNoWriteBarrier(request, AsyncGeneratorRequest::kValueOffset,
                                 resume_value);
  StoreObjectFieldNoWriteBarrier(request, AsyncGeneratorRequest::kPromiseOffset,
                                 promise);
  StoreObjectFieldRoot(request, AsyncGeneratorRequest::kNextOffset,
                       Heap::kUndefinedValueRootIndex);
  return request;
}

void AsyncGeneratorBuiltinsAssembler::AsyncGeneratorAwaitResumeClosure(
    Node* context, Node* value,
    JSAsyncGeneratorObject::ResumeMode resume_mode) {
  Node* const generator =
      LoadContextElement(context, AwaitContext::kGeneratorSlot);
  CSA_SLOW_ASSERT(this, TaggedIsAsyncGenerator(generator));

#if defined(DEBUG) && defined(ENABLE_SLOW_DCHECKS)
  Node* const awaited_promise = LoadGeneratorAwaitedPromise(generator);
  CSA_SLOW_ASSERT(this, HasInstanceType(awaited_promise, JS_PROMISE_TYPE));
  CSA_SLOW_ASSERT(this, Word32NotEqual(PromiseStatus(awaited_promise),
                                       Int32Constant(v8::Promise::kPending)));
#endif

  ClearAwaitedPromise(generator);

  CSA_SLOW_ASSERT(this, IsGeneratorSuspended(generator));

  // Remember the {resume_mode} for the {generator}.
  StoreObjectFieldNoWriteBarrier(generator,
                                 JSGeneratorObject::kResumeModeOffset,
                                 SmiConstant(resume_mode));

  CallStub(CodeFactory::ResumeGenerator(isolate()), context, value, generator);

  TailCallBuiltin(Builtins::kAsyncGeneratorResumeNext, context, generator);
}

template <typename Descriptor>
void AsyncGeneratorBuiltinsAssembler::AsyncGeneratorAwait(bool is_catchable) {
  Node* generator = Parameter(Descriptor::kGenerator);
  Node* value = Parameter(Descriptor::kAwaited);
  Node* context = Parameter(Descriptor::kContext);

  CSA_SLOW_ASSERT(this, TaggedIsAsyncGenerator(generator));

  Node* const request = LoadFirstAsyncGeneratorRequestFromQueue(generator);
  CSA_ASSERT(this, IsNotUndefined(request));

  ContextInitializer init_closure_context = [&](Node* context) {
    StoreContextElementNoWriteBarrier(context, AwaitContext::kGeneratorSlot,
                                      generator);
  };

  Node* outer_promise =
      LoadObjectField(request, AsyncGeneratorRequest::kPromiseOffset);

  const int resolve_index = Context::ASYNC_GENERATOR_AWAIT_RESOLVE_SHARED_FUN;
  const int reject_index = Context::ASYNC_GENERATOR_AWAIT_REJECT_SHARED_FUN;

  Node* promise =
      Await(context, generator, value, outer_promise, AwaitContext::kLength,
            init_closure_context, resolve_index, reject_index, is_catchable);

  CSA_SLOW_ASSERT(this, IsGeneratorNotSuspendedForAwait(generator));
  StoreObjectField(generator, JSAsyncGeneratorObject::kAwaitedPromiseOffset,
                   promise);
  Return(UndefinedConstant());
}

void AsyncGeneratorBuiltinsAssembler::AddAsyncGeneratorRequestToQueue(
    Node* generator, Node* request) {
  VARIABLE(var_current, MachineRepresentation::kTagged);
  Label empty(this), loop(this, &var_current), done(this);

  var_current.Bind(
      LoadObjectField(generator, JSAsyncGeneratorObject::kQueueOffset));
  Branch(IsUndefined(var_current.value()), &empty, &loop);

  BIND(&empty);
  {
    StoreObjectField(generator, JSAsyncGeneratorObject::kQueueOffset, request);
    Goto(&done);
  }

  BIND(&loop);
  {
    Label loop_next(this), next_empty(this);
    Node* current = var_current.value();
    Node* next = LoadObjectField(current, AsyncGeneratorRequest::kNextOffset);

    Branch(IsUndefined(next), &next_empty, &loop_next);
    BIND(&next_empty);
    {
      StoreObjectField(current, AsyncGeneratorRequest::kNextOffset, request);
      Goto(&done);
    }

    BIND(&loop_next);
    {
      var_current.Bind(next);
      Goto(&loop);
    }
  }
  BIND(&done);
}

Node* AsyncGeneratorBuiltinsAssembler::TakeFirstAsyncGeneratorRequestFromQueue(
    Node* generator) {
  // Removes and returns the first AsyncGeneratorRequest from a
  // JSAsyncGeneratorObject's queue. Asserts that the queue is not empty.
  CSA_ASSERT(this, TaggedIsAsyncGenerator(generator));
  Node* request =
      LoadObjectField(generator, JSAsyncGeneratorObject::kQueueOffset);
  CSA_ASSERT(this, IsNotUndefined(request));

  Node* next = LoadObjectField(request, AsyncGeneratorRequest::kNextOffset);

  StoreObjectField(generator, JSAsyncGeneratorObject::kQueueOffset, next);
  return request;
}
}  // namespace

// https://tc39.github.io/proposal-async-iteration/
// Section #sec-asyncgenerator-prototype-next
TF_BUILTIN(AsyncGeneratorPrototypeNext, AsyncGeneratorBuiltinsAssembler) {
  const int kValueArg = 0;

  Node* argc =
      ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
  CodeStubArguments args(this, argc);

  Node* generator = args.GetReceiver();
  Node* value = args.GetOptionalArgumentValue(kValueArg);
  Node* context = Parameter(BuiltinDescriptor::kContext);

  AsyncGeneratorEnqueue(&args, context, generator, value,
                        JSAsyncGeneratorObject::kNext,
                        "[AsyncGenerator].prototype.next");
}

// https://tc39.github.io/proposal-async-iteration/
// Section #sec-asyncgenerator-prototype-return
TF_BUILTIN(AsyncGeneratorPrototypeReturn, AsyncGeneratorBuiltinsAssembler) {
  const int kValueArg = 0;

  Node* argc =
      ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
  CodeStubArguments args(this, argc);

  Node* generator = args.GetReceiver();
  Node* value = args.GetOptionalArgumentValue(kValueArg);
  Node* context = Parameter(BuiltinDescriptor::kContext);

  AsyncGeneratorEnqueue(&args, context, generator, value,
                        JSAsyncGeneratorObject::kReturn,
                        "[AsyncGenerator].prototype.return");
}

// https://tc39.github.io/proposal-async-iteration/
// Section #sec-asyncgenerator-prototype-throw
TF_BUILTIN(AsyncGeneratorPrototypeThrow, AsyncGeneratorBuiltinsAssembler) {
  const int kValueArg = 0;

  Node* argc =
      ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
  CodeStubArguments args(this, argc);

  Node* generator = args.GetReceiver();
  Node* value = args.GetOptionalArgumentValue(kValueArg);
  Node* context = Parameter(BuiltinDescriptor::kContext);

  AsyncGeneratorEnqueue(&args, context, generator, value,
                        JSAsyncGeneratorObject::kThrow,
                        "[AsyncGenerator].prototype.throw");
}

TF_BUILTIN(AsyncGeneratorAwaitResolveClosure, AsyncGeneratorBuiltinsAssembler) {
  Node* value = Parameter(Descriptor::kValue);
  Node* context = Parameter(Descriptor::kContext);
  AsyncGeneratorAwaitResumeClosure(context, value,
                                   JSAsyncGeneratorObject::kNext);
}

TF_BUILTIN(AsyncGeneratorAwaitRejectClosure, AsyncGeneratorBuiltinsAssembler) {
  Node* value = Parameter(Descriptor::kValue);
  Node* context = Parameter(Descriptor::kContext);
  AsyncGeneratorAwaitResumeClosure(context, value,
                                   JSAsyncGeneratorObject::kThrow);
}

TF_BUILTIN(AsyncGeneratorAwaitUncaught, AsyncGeneratorBuiltinsAssembler) {
  const bool kIsCatchable = false;
  AsyncGeneratorAwait<Descriptor>(kIsCatchable);
}

TF_BUILTIN(AsyncGeneratorAwaitCaught, AsyncGeneratorBuiltinsAssembler) {
  const bool kIsCatchable = true;
  AsyncGeneratorAwait<Descriptor>(kIsCatchable);
}

TF_BUILTIN(AsyncGeneratorResumeNext, AsyncGeneratorBuiltinsAssembler) {
  typedef AsyncGeneratorResumeNextDescriptor Descriptor;
  Node* const generator = Parameter(Descriptor::kGenerator);
  Node* const context = Parameter(Descriptor::kContext);

  // The penultimate step of proposal-async-iteration/#sec-asyncgeneratorresolve
  // and proposal-async-iteration/#sec-asyncgeneratorreject both recursively
  // invoke AsyncGeneratorResumeNext() again.
  //
  // This implementation does not implement this recursively, but instead
  // performs a loop in AsyncGeneratorResumeNext, which  continues as long as
  // there is an AsyncGeneratorRequest in the queue, and as long as the
  // generator is not suspended due to an AwaitExpression.
  VARIABLE(var_state, MachineRepresentation::kTaggedSigned,
           LoadGeneratorState(generator));
  VARIABLE(var_next, MachineRepresentation::kTagged,
           LoadFirstAsyncGeneratorRequestFromQueue(generator));
  Variable* loop_variables[] = {&var_state, &var_next};
  Label start(this, 2, loop_variables);
  Goto(&start);
  BIND(&start);

  CSA_ASSERT(this, IsGeneratorNotExecuting(generator));

  // Stop resuming if suspended for Await.
  ReturnIf(IsGeneratorSuspendedForAwait(generator), UndefinedConstant());

  // Stop resuming if request queue is empty.
  ReturnIf(IsUndefined(var_next.value()), UndefinedConstant());

  Node* const next = var_next.value();
  Node* const resume_type = LoadResumeTypeFromAsyncGeneratorRequest(next);

  Label if_abrupt(this), if_normal(this), resume_generator(this);
  Branch(IsAbruptResumeType(resume_type), &if_abrupt, &if_normal);
  BIND(&if_abrupt);
  {
    Label settle_promise(this), if_return(this), if_throw(this);
    GotoIfNot(IsGeneratorStateSuspendedAtStart(var_state.value()),
              &settle_promise);
    CloseGenerator(generator);
    var_state.Bind(SmiConstant(JSGeneratorObject::kGeneratorClosed));

    Goto(&settle_promise);
    BIND(&settle_promise);

    Node* next_value = LoadValueFromAsyncGeneratorRequest(next);
    Branch(SmiEqual(resume_type, SmiConstant(JSGeneratorObject::kReturn)),
           &if_return, &if_throw);

    BIND(&if_return);
    // For "return" completions, await the sent value. If the Await succeeds,
    // and the generator is not closed, resume the generator with a "return"
    // completion to allow `finally` blocks to be evaluated. Otherwise, perform
    // AsyncGeneratorResolve(awaitedValue, true). If the await fails and the
    // generator is not closed, resume the generator with a "throw" completion.
    // If the generator was closed, perform AsyncGeneratorReject(thrownValue).
    // In all cases, the last step is to call AsyncGeneratorResumeNext.
    Node* is_caught = CallRuntime(Runtime::kAsyncGeneratorHasCatchHandlerForPC,
                                  context, generator);
    TailCallBuiltin(Builtins::kAsyncGeneratorReturn, context, generator,
                    next_value, is_caught);

    BIND(&if_throw);
    GotoIfNot(IsGeneratorStateClosed(var_state.value()), &resume_generator);
    CallBuiltin(Builtins::kAsyncGeneratorReject, context, generator,
                next_value);
    var_next.Bind(LoadFirstAsyncGeneratorRequestFromQueue(generator));
    Goto(&start);
  }

  BIND(&if_normal);
  {
    GotoIfNot(IsGeneratorStateClosed(var_state.value()), &resume_generator);
    CallBuiltin(Builtins::kAsyncGeneratorResolve, context, generator,
                UndefinedConstant(), TrueConstant());
    var_state.Bind(LoadGeneratorState(generator));
    var_next.Bind(LoadFirstAsyncGeneratorRequestFromQueue(generator));
    Goto(&start);
  }

  BIND(&resume_generator);
  {
    // Remember the {resume_type} for the {generator}.
    StoreObjectFieldNoWriteBarrier(
        generator, JSGeneratorObject::kResumeModeOffset, resume_type);
    CallStub(CodeFactory::ResumeGenerator(isolate()), context,
             LoadValueFromAsyncGeneratorRequest(next), generator);
    var_state.Bind(LoadGeneratorState(generator));
    var_next.Bind(LoadFirstAsyncGeneratorRequestFromQueue(generator));
    Goto(&start);
  }
}

TF_BUILTIN(AsyncGeneratorResolve, AsyncGeneratorBuiltinsAssembler) {
  Node* const generator = Parameter(Descriptor::kGenerator);
  Node* const value = Parameter(Descriptor::kValue);
  Node* const done = Parameter(Descriptor::kDone);
  Node* const context = Parameter(Descriptor::kContext);

  CSA_SLOW_ASSERT(this, TaggedIsAsyncGenerator(generator));
  CSA_ASSERT(this, IsGeneratorNotSuspendedForAwait(generator));

  // If this assertion fails, the `value` component was not Awaited as it should
  // have been, per https://github.com/tc39/proposal-async-iteration/pull/102/.
  CSA_SLOW_ASSERT(this, TaggedDoesntHaveInstanceType(value, JS_PROMISE_TYPE));

  Node* const next = TakeFirstAsyncGeneratorRequestFromQueue(generator);
  Node* const promise = LoadPromiseFromAsyncGeneratorRequest(next);

  // Let iteratorResult be CreateIterResultObject(value, done).
  Node* const iter_result = Allocate(JSIteratorResult::kSize);
  {
    Node* map = LoadContextElement(LoadNativeContext(context),
                                   Context::ITERATOR_RESULT_MAP_INDEX);
    StoreMapNoWriteBarrier(iter_result, map);
    StoreObjectFieldRoot(iter_result, JSIteratorResult::kPropertiesOrHashOffset,
                         Heap::kEmptyFixedArrayRootIndex);
    StoreObjectFieldRoot(iter_result, JSIteratorResult::kElementsOffset,
                         Heap::kEmptyFixedArrayRootIndex);
    StoreObjectFieldNoWriteBarrier(iter_result, JSIteratorResult::kValueOffset,
                                   value);
    StoreObjectFieldNoWriteBarrier(iter_result, JSIteratorResult::kDoneOffset,
                                   done);
  }

  // Perform Call(promiseCapability.[[Resolve]], undefined, «iteratorResult»).
  CallBuiltin(Builtins::kResolveNativePromise, context, promise, iter_result);

  // Per spec, AsyncGeneratorResolve() returns undefined. However, for the
  // benefit of %TraceExit(), return the Promise.
  Return(promise);
}

TF_BUILTIN(AsyncGeneratorReject, AsyncGeneratorBuiltinsAssembler) {
  typedef AsyncGeneratorRejectDescriptor Descriptor;
  Node* const generator = Parameter(Descriptor::kGenerator);
  Node* const value = Parameter(Descriptor::kValue);
  Node* const context = Parameter(Descriptor::kContext);

  Node* const next = TakeFirstAsyncGeneratorRequestFromQueue(generator);
  Node* const promise = LoadPromiseFromAsyncGeneratorRequest(next);

  Return(CallBuiltin(Builtins::kRejectNativePromise, context, promise, value,
                     TrueConstant()));
}

TF_BUILTIN(AsyncGeneratorYield, AsyncGeneratorBuiltinsAssembler) {
  Node* const generator = Parameter(Descriptor::kGenerator);
  Node* const value = Parameter(Descriptor::kValue);
  Node* const is_caught = Parameter(Descriptor::kIsCaught);
  Node* const context = Parameter(Descriptor::kContext);

  Node* const request = LoadFirstAsyncGeneratorRequestFromQueue(generator);
  Node* const outer_promise = LoadPromiseFromAsyncGeneratorRequest(request);

  ContextInitializer init_closure_context = [&](Node* context) {
    StoreContextElementNoWriteBarrier(context, AwaitContext::kGeneratorSlot,
                                      generator);
  };

  const int on_resolve = Context::ASYNC_GENERATOR_YIELD_RESOLVE_SHARED_FUN;
  const int on_reject = Context::ASYNC_GENERATOR_AWAIT_REJECT_SHARED_FUN;

  Node* const promise =
      Await(context, generator, value, outer_promise, AwaitContext::kLength,
            init_closure_context, on_resolve, on_reject, is_caught);
  StoreObjectField(generator, JSAsyncGeneratorObject::kAwaitedPromiseOffset,
                   promise);
  Return(UndefinedConstant());
}

TF_BUILTIN(AsyncGeneratorYieldResolveClosure, AsyncGeneratorBuiltinsAssembler) {
  Node* const context = Parameter(Descriptor::kContext);
  Node* const value = Parameter(Descriptor::kValue);
  Node* const generator =
      LoadContextElement(context, AwaitContext::kGeneratorSlot);

  CSA_SLOW_ASSERT(this, IsGeneratorSuspendedForAwait(generator));
  ClearAwaitedPromise(generator);

  // Per proposal-async-iteration/#sec-asyncgeneratoryield step 9
  // Return ! AsyncGeneratorResolve(_F_.[[Generator]], _value_, *false*).
  CallBuiltin(Builtins::kAsyncGeneratorResolve, context, generator, value,
              FalseConstant());

  TailCallBuiltin(Builtins::kAsyncGeneratorResumeNext, context, generator);
}

TF_BUILTIN(AsyncGeneratorReturn, AsyncGeneratorBuiltinsAssembler) {
  // AsyncGeneratorReturn is called when resuming requests with "return" resume
  // modes. It is similar to AsyncGeneratorAwait(), but selects different
  // resolve/reject closures depending on whether or not the generator is marked
  // as closed.
  //
  // In particular, non-closed generators will resume the generator with either
  // "return" or "throw" resume modes, allowing finally blocks or catch blocks
  // to be evaluated, as if the `await` were performed within the body of the
  // generator. (per proposal-async-iteration/#sec-asyncgeneratoryield step 8.b)
  //
  // Closed generators do not resume the generator in the resolve/reject
  // closures, but instead simply perform AsyncGeneratorResolve or
  // AsyncGeneratorReject with the awaited value
  // (per proposal-async-iteration/#sec-asyncgeneratorresumenext step 10.b.i)
  //
  // In all cases, the final step is to jump back to AsyncGeneratorResumeNext.
  Node* const generator = Parameter(Descriptor::kGenerator);
  Node* const value = Parameter(Descriptor::kValue);
  Node* const is_caught = Parameter(Descriptor::kIsCaught);
  Node* const req = LoadFirstAsyncGeneratorRequestFromQueue(generator);
  CSA_ASSERT(this, IsNotUndefined(req));

  Label perform_await(this);
  VARIABLE(var_on_resolve, MachineType::PointerRepresentation(),
           IntPtrConstant(
               Context::ASYNC_GENERATOR_RETURN_CLOSED_RESOLVE_SHARED_FUN));
  VARIABLE(
      var_on_reject, MachineType::PointerRepresentation(),
      IntPtrConstant(Context::ASYNC_GENERATOR_RETURN_CLOSED_REJECT_SHARED_FUN));

  Node* const state = LoadGeneratorState(generator);
  GotoIf(IsGeneratorStateClosed(state), &perform_await);
  var_on_resolve.Bind(
      IntPtrConstant(Context::ASYNC_GENERATOR_RETURN_RESOLVE_SHARED_FUN));
  var_on_reject.Bind(
      IntPtrConstant(Context::ASYNC_GENERATOR_AWAIT_REJECT_SHARED_FUN));
  Goto(&perform_await);

  BIND(&perform_await);

  ContextInitializer init_closure_context = [&](Node* context) {
    StoreContextElementNoWriteBarrier(context, AwaitContext::kGeneratorSlot,
                                      generator);
  };

  Node* const context = Parameter(Descriptor::kContext);
  Node* const outer_promise = LoadPromiseFromAsyncGeneratorRequest(req);
  Node* const promise =
      Await(context, generator, value, outer_promise, AwaitContext::kLength,
            init_closure_context, var_on_resolve.value(), var_on_reject.value(),
            is_caught);

  CSA_SLOW_ASSERT(this, IsGeneratorNotSuspendedForAwait(generator));
  StoreObjectField(generator, JSAsyncGeneratorObject::kAwaitedPromiseOffset,
                   promise);
  Return(UndefinedConstant());
}

// On-resolve closure for Await in AsyncGeneratorReturn
// Resume the generator with "return" resume_mode, and finally perform
// AsyncGeneratorResumeNext. Per
// proposal-async-iteration/#sec-asyncgeneratoryield step 8.e
TF_BUILTIN(AsyncGeneratorReturnResolveClosure,
           AsyncGeneratorBuiltinsAssembler) {
  Node* const context = Parameter(Descriptor::kContext);
  Node* const value = Parameter(Descriptor::kValue);
  AsyncGeneratorAwaitResumeClosure(context, value, JSGeneratorObject::kReturn);
}

// On-resolve closure for Await in AsyncGeneratorReturn
// Perform AsyncGeneratorResolve({awaited_value}, true) and finally perform
// AsyncGeneratorResumeNext.
TF_BUILTIN(AsyncGeneratorReturnClosedResolveClosure,
           AsyncGeneratorBuiltinsAssembler) {
  Node* const context = Parameter(Descriptor::kContext);
  Node* const value = Parameter(Descriptor::kValue);
  Node* const generator =
      LoadContextElement(context, AwaitContext::kGeneratorSlot);

  CSA_SLOW_ASSERT(this, IsGeneratorSuspendedForAwait(generator));
  ClearAwaitedPromise(generator);

  // https://tc39.github.io/proposal-async-iteration/
  //    #async-generator-resume-next-return-processor-fulfilled step 2:
  //  Return ! AsyncGeneratorResolve(_F_.[[Generator]], _value_, *true*).
  CallBuiltin(Builtins::kAsyncGeneratorResolve, context, generator, value,
              TrueConstant());

  TailCallBuiltin(Builtins::kAsyncGeneratorResumeNext, context, generator);
}

TF_BUILTIN(AsyncGeneratorReturnClosedRejectClosure,
           AsyncGeneratorBuiltinsAssembler) {
  Node* const context = Parameter(Descriptor::kContext);
  Node* const value = Parameter(Descriptor::kValue);
  Node* const generator =
      LoadContextElement(context, AwaitContext::kGeneratorSlot);

  CSA_SLOW_ASSERT(this, IsGeneratorSuspendedForAwait(generator));
  ClearAwaitedPromise(generator);

  // https://tc39.github.io/proposal-async-iteration/
  //    #async-generator-resume-next-return-processor-rejected step 2:
  // Return ! AsyncGeneratorReject(_F_.[[Generator]], _reason_).
  CallBuiltin(Builtins::kAsyncGeneratorReject, context, generator, value);

  TailCallBuiltin(Builtins::kAsyncGeneratorResumeNext, context, generator);
}

}  // namespace internal
}  // namespace v8
