// Copyright 2016 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"

namespace v8 {
namespace internal {

using compiler::Node;

namespace {
// Describe fields of Context associated with the AsyncIterator unwrap closure.
class ValueUnwrapContext {
 public:
  enum Fields { kDoneSlot = Context::MIN_CONTEXT_SLOTS, kLength };
};

}  // namespace

Node* AsyncBuiltinsAssembler::Await(
    Node* context, Node* generator, Node* value, Node* outer_promise,
    int context_length, const ContextInitializer& init_closure_context,
    int on_resolve_context_index, int on_reject_context_index,
    bool is_predicted_as_caught) {
  DCHECK_GE(context_length, Context::MIN_CONTEXT_SLOTS);

  Node* const native_context = LoadNativeContext(context);

#ifdef DEBUG
  {
    Node* const map = LoadContextElement(
        native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
    Node* const instance_size = LoadMapInstanceSize(map);
    // Assert that the strict function map has an instance size is
    // JSFunction::kSize
    CSA_ASSERT(this, WordEqual(instance_size, IntPtrConstant(JSFunction::kSize /
                                                             kPointerSize)));
  }
#endif

#ifdef DEBUG
  {
    Node* const promise_fun =
        LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
    Node* const map =
        LoadObjectField(promise_fun, JSFunction::kPrototypeOrInitialMapOffset);
    Node* const instance_size = LoadMapInstanceSize(map);
    // Assert that the JSPromise map has an instance size is
    // JSPromise::kSize
    CSA_ASSERT(this,
               WordEqual(instance_size,
                         IntPtrConstant(JSPromise::kSizeWithEmbedderFields /
                                        kPointerSize)));
  }
#endif

  static const int kWrappedPromiseOffset = FixedArray::SizeFor(context_length);
  static const int kThrowawayPromiseOffset =
      kWrappedPromiseOffset + JSPromise::kSizeWithEmbedderFields;
  static const int kResolveClosureOffset =
      kThrowawayPromiseOffset + JSPromise::kSizeWithEmbedderFields;
  static const int kRejectClosureOffset =
      kResolveClosureOffset + JSFunction::kSize;
  static const int kTotalSize = kRejectClosureOffset + JSFunction::kSize;

  Node* const base = AllocateInNewSpace(kTotalSize);
  Node* const closure_context = base;
  {
    // Initialize closure context
    InitializeFunctionContext(native_context, closure_context, context_length);
    init_closure_context(closure_context);
  }

  // Let promiseCapability be ! NewPromiseCapability(%Promise%).
  Node* const promise_fun =
      LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
  Node* const promise_map =
      LoadObjectField(promise_fun, JSFunction::kPrototypeOrInitialMapOffset);
  Node* const wrapped_value = InnerAllocate(base, kWrappedPromiseOffset);
  {
    // Initialize Promise
    StoreMapNoWriteBarrier(wrapped_value, promise_map);
    InitializeJSObjectFromMap(
        wrapped_value, promise_map,
        IntPtrConstant(JSPromise::kSizeWithEmbedderFields),
        EmptyFixedArrayConstant(), EmptyFixedArrayConstant());
    PromiseInit(wrapped_value);
  }

  Node* const throwaway = InnerAllocate(base, kThrowawayPromiseOffset);
  {
    // Initialize throwawayPromise
    StoreMapNoWriteBarrier(throwaway, promise_map);
    InitializeJSObjectFromMap(
        throwaway, promise_map,
        IntPtrConstant(JSPromise::kSizeWithEmbedderFields),
        EmptyFixedArrayConstant(), EmptyFixedArrayConstant());
    PromiseInit(throwaway);
  }

  Node* const on_resolve = InnerAllocate(base, kResolveClosureOffset);
  {
    // Initialize resolve handler
    InitializeNativeClosure(closure_context, native_context, on_resolve,
                            on_resolve_context_index);
  }

  Node* const on_reject = InnerAllocate(base, kRejectClosureOffset);
  {
    // Initialize reject handler
    InitializeNativeClosure(closure_context, native_context, on_reject,
                            on_reject_context_index);
  }

  {
    // Add PromiseHooks if needed
    Label next(this);
    GotoIfNot(IsPromiseHookEnabledOrDebugIsActive(), &next);
    CallRuntime(Runtime::kPromiseHookInit, context, wrapped_value,
                outer_promise);
    CallRuntime(Runtime::kPromiseHookInit, context, throwaway, wrapped_value);
    Goto(&next);
    BIND(&next);
  }

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

  // The Promise will be thrown away and not handled, but it shouldn't trigger
  // unhandled reject events as its work is done
  PromiseSetHasHandler(throwaway);

  Label do_perform_promise_then(this);
  GotoIfNot(IsDebugActive(), &do_perform_promise_then);
  {
    Label common(this);
    GotoIf(TaggedIsSmi(value), &common);
    GotoIfNot(HasInstanceType(value, JS_PROMISE_TYPE), &common);
    {
      // Mark the reject handler callback to be a forwarding edge, rather
      // than a meaningful catch handler
      Node* const key =
          HeapConstant(factory()->promise_forwarding_handler_symbol());
      CallRuntime(Runtime::kSetProperty, context, on_reject, key,
                  TrueConstant(), SmiConstant(STRICT));

      if (is_predicted_as_caught) PromiseSetHandledHint(value);
    }

    Goto(&common);
    BIND(&common);
    // Mark the dependency to outer Promise in case the throwaway Promise is
    // found on the Promise stack
    CSA_SLOW_ASSERT(this, HasInstanceType(outer_promise, JS_PROMISE_TYPE));

    Node* const key = HeapConstant(factory()->promise_handled_by_symbol());
    CallRuntime(Runtime::kSetProperty, context, throwaway, key, outer_promise,
                SmiConstant(STRICT));
  }

  Goto(&do_perform_promise_then);
  BIND(&do_perform_promise_then);

  CallBuiltin(Builtins::kPerformNativePromiseThen, context, wrapped_value,
              on_resolve, on_reject, throwaway);

  return wrapped_value;
}

void AsyncBuiltinsAssembler::InitializeNativeClosure(Node* context,
                                                     Node* native_context,
                                                     Node* function,
                                                     int context_index) {
  Node* const function_map = LoadContextElement(
      native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
  StoreMapNoWriteBarrier(function, function_map);
  StoreObjectFieldRoot(function, JSObject::kPropertiesOffset,
                       Heap::kEmptyFixedArrayRootIndex);
  StoreObjectFieldRoot(function, JSObject::kElementsOffset,
                       Heap::kEmptyFixedArrayRootIndex);
  StoreObjectFieldRoot(function, JSFunction::kFeedbackVectorOffset,
                       Heap::kUndefinedCellRootIndex);
  StoreObjectFieldRoot(function, JSFunction::kPrototypeOrInitialMapOffset,
                       Heap::kTheHoleValueRootIndex);

  Node* shared_info = LoadContextElement(native_context, context_index);
  CSA_ASSERT(this, IsSharedFunctionInfo(shared_info));
  StoreObjectFieldNoWriteBarrier(
      function, JSFunction::kSharedFunctionInfoOffset, shared_info);
  StoreObjectFieldNoWriteBarrier(function, JSFunction::kContextOffset, context);

  Node* const code = BitcastTaggedToWord(
      LoadObjectField(shared_info, SharedFunctionInfo::kCodeOffset));
  Node* const code_entry =
      IntPtrAdd(code, IntPtrConstant(Code::kHeaderSize - kHeapObjectTag));
  StoreObjectFieldNoWriteBarrier(function, JSFunction::kCodeEntryOffset,
                                 code_entry,
                                 MachineType::PointerRepresentation());
  StoreObjectFieldRoot(function, JSFunction::kNextFunctionLinkOffset,
                       Heap::kUndefinedValueRootIndex);
}

Node* AsyncBuiltinsAssembler::CreateUnwrapClosure(Node* native_context,
                                                  Node* done) {
  Node* const map = LoadContextElement(
      native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
  Node* const on_fulfilled_shared = LoadContextElement(
      native_context, Context::ASYNC_ITERATOR_VALUE_UNWRAP_SHARED_FUN);
  CSA_ASSERT(this,
             HasInstanceType(on_fulfilled_shared, SHARED_FUNCTION_INFO_TYPE));
  Node* const closure_context =
      AllocateAsyncIteratorValueUnwrapContext(native_context, done);
  return AllocateFunctionWithMapAndContext(map, on_fulfilled_shared,
                                           closure_context);
}

Node* AsyncBuiltinsAssembler::AllocateAsyncIteratorValueUnwrapContext(
    Node* native_context, Node* done) {
  CSA_ASSERT(this, IsNativeContext(native_context));
  CSA_ASSERT(this, IsBoolean(done));

  Node* const context =
      CreatePromiseContext(native_context, ValueUnwrapContext::kLength);
  StoreContextElementNoWriteBarrier(context, ValueUnwrapContext::kDoneSlot,
                                    done);
  return context;
}

TF_BUILTIN(AsyncIteratorValueUnwrap, AsyncBuiltinsAssembler) {
  Node* const value = Parameter(Descriptor::kValue);
  Node* const context = Parameter(Descriptor::kContext);

  Node* const done = LoadContextElement(context, ValueUnwrapContext::kDoneSlot);
  CSA_ASSERT(this, IsBoolean(done));

  Node* const unwrapped_value =
      CallBuiltin(Builtins::kCreateIterResultObject, context, value, done);

  Return(unwrapped_value);
}

}  // namespace internal
}  // namespace v8
