// 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/api-arguments-inl.h"
#include "src/api-natives.h"
#include "src/builtins/builtins-utils-inl.h"
#include "src/builtins/builtins.h"
#include "src/counters.h"
#include "src/log.h"
#include "src/objects-inl.h"
#include "src/objects/templates.h"
#include "src/prototype.h"
#include "src/visitors.h"

namespace v8 {
namespace internal {

namespace {

// Returns the holder JSObject if the function can legally be called with this
// receiver.  Returns nullptr if the call is illegal.
// TODO(dcarney): CallOptimization duplicates this logic, merge.
JSReceiver GetCompatibleReceiver(Isolate* isolate, FunctionTemplateInfo info,
                                 JSReceiver receiver) {
  Object* recv_type = info->signature();
  // No signature, return holder.
  if (!recv_type->IsFunctionTemplateInfo()) return receiver;
  // A Proxy cannot have been created from the signature template.
  if (!receiver->IsJSObject()) return JSReceiver();

  JSObject js_obj_receiver = JSObject::cast(receiver);
  FunctionTemplateInfo signature = FunctionTemplateInfo::cast(recv_type);

  // Check the receiver. Fast path for receivers with no hidden prototypes.
  if (signature->IsTemplateFor(js_obj_receiver)) return receiver;
  if (!js_obj_receiver->map()->has_hidden_prototype()) return JSReceiver();
  for (PrototypeIterator iter(isolate, js_obj_receiver, kStartAtPrototype,
                              PrototypeIterator::END_AT_NON_HIDDEN);
       !iter.IsAtEnd(); iter.Advance()) {
    JSObject current = iter.GetCurrent<JSObject>();
    if (signature->IsTemplateFor(current)) return current;
  }
  return JSReceiver();
}

template <bool is_construct>
V8_WARN_UNUSED_RESULT MaybeHandle<Object> HandleApiCallHelper(
    Isolate* isolate, Handle<HeapObject> function,
    Handle<HeapObject> new_target, Handle<FunctionTemplateInfo> fun_data,
    Handle<Object> receiver, BuiltinArguments args) {
  Handle<JSReceiver> js_receiver;
  JSReceiver raw_holder;
  if (is_construct) {
    DCHECK(args.receiver()->IsTheHole(isolate));
    if (fun_data->GetInstanceTemplate()->IsUndefined(isolate)) {
      v8::Local<ObjectTemplate> templ =
          ObjectTemplate::New(reinterpret_cast<v8::Isolate*>(isolate),
                              ToApiHandle<v8::FunctionTemplate>(fun_data));
      FunctionTemplateInfo::SetInstanceTemplate(isolate, fun_data,
                                                Utils::OpenHandle(*templ));
    }
    Handle<ObjectTemplateInfo> instance_template(
        ObjectTemplateInfo::cast(fun_data->GetInstanceTemplate()), isolate);
    ASSIGN_RETURN_ON_EXCEPTION(
        isolate, js_receiver,
        ApiNatives::InstantiateObject(isolate, instance_template,
                                      Handle<JSReceiver>::cast(new_target)),
        Object);
    args.set_at(0, *js_receiver);
    DCHECK_EQ(*js_receiver, *args.receiver());

    raw_holder = *js_receiver;
  } else {
    DCHECK(receiver->IsJSReceiver());
    js_receiver = Handle<JSReceiver>::cast(receiver);

    if (!fun_data->accept_any_receiver() &&
        js_receiver->IsAccessCheckNeeded()) {
      // Proxies never need access checks.
      DCHECK(js_receiver->IsJSObject());
      Handle<JSObject> js_obj_receiver = Handle<JSObject>::cast(js_receiver);
      if (!isolate->MayAccess(handle(isolate->context(), isolate),
                              js_obj_receiver)) {
        isolate->ReportFailedAccessCheck(js_obj_receiver);
        RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
        return isolate->factory()->undefined_value();
      }
    }

    raw_holder = GetCompatibleReceiver(isolate, *fun_data, *js_receiver);

    if (raw_holder.is_null()) {
      // This function cannot be called with the given receiver.  Abort!
      THROW_NEW_ERROR(
          isolate, NewTypeError(MessageTemplate::kIllegalInvocation), Object);
    }
  }

  Object* raw_call_data = fun_data->call_code();
  if (!raw_call_data->IsUndefined(isolate)) {
    DCHECK(raw_call_data->IsCallHandlerInfo());
    CallHandlerInfo call_data = CallHandlerInfo::cast(raw_call_data);
    Object* data_obj = call_data->data();

    FunctionCallbackArguments custom(isolate, data_obj, *function, raw_holder,
                                     *new_target, args.address_of_arg_at(1),
                                     args.length() - 1);
    Handle<Object> result = custom.Call(call_data);

    RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
    if (result.is_null()) {
      if (is_construct) return js_receiver;
      return isolate->factory()->undefined_value();
    }
    // Rebox the result.
    result->VerifyApiCallResultType();
    if (!is_construct || result->IsJSReceiver())
      return handle(*result, isolate);
  }

  return js_receiver;
}

}  // anonymous namespace

BUILTIN(HandleApiCall) {
  HandleScope scope(isolate);
  Handle<JSFunction> function = args.target();
  Handle<Object> receiver = args.receiver();
  Handle<HeapObject> new_target = args.new_target();
  Handle<FunctionTemplateInfo> fun_data(function->shared()->get_api_func_data(),
                                        isolate);
  if (new_target->IsJSReceiver()) {
    RETURN_RESULT_OR_FAILURE(
        isolate, HandleApiCallHelper<true>(isolate, function, new_target,
                                           fun_data, receiver, args));
  } else {
    RETURN_RESULT_OR_FAILURE(
        isolate, HandleApiCallHelper<false>(isolate, function, new_target,
                                            fun_data, receiver, args));
  }
}

namespace {

class RelocatableArguments : public BuiltinArguments, public Relocatable {
 public:
  RelocatableArguments(Isolate* isolate, int length, Address* arguments)
      : BuiltinArguments(length, arguments), Relocatable(isolate) {}

  inline void IterateInstance(RootVisitor* v) override {
    if (length() == 0) return;
    v->VisitRootPointers(Root::kRelocatable, nullptr, first_slot(),
                         last_slot() + 1);
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(RelocatableArguments);
};

}  // namespace

MaybeHandle<Object> Builtins::InvokeApiFunction(Isolate* isolate,
                                                bool is_construct,
                                                Handle<HeapObject> function,
                                                Handle<Object> receiver,
                                                int argc, Handle<Object> args[],
                                                Handle<HeapObject> new_target) {
  RuntimeCallTimerScope timer(isolate,
                              RuntimeCallCounterId::kInvokeApiFunction);
  DCHECK(function->IsFunctionTemplateInfo() ||
         (function->IsJSFunction() &&
          JSFunction::cast(*function)->shared()->IsApiFunction()));

  // Do proper receiver conversion for non-strict mode api functions.
  if (!is_construct && !receiver->IsJSReceiver()) {
    if (function->IsFunctionTemplateInfo() ||
        is_sloppy(JSFunction::cast(*function)->shared()->language_mode())) {
      ASSIGN_RETURN_ON_EXCEPTION(isolate, receiver,
                                 Object::ConvertReceiver(isolate, receiver),
                                 Object);
    }
  }

  if (function->IsFunctionTemplateInfo()) {
    Handle<FunctionTemplateInfo> info =
        Handle<FunctionTemplateInfo>::cast(function);
    // If we need to break at function entry, go the long way. Instantiate the
    // function, use the DebugBreakTrampoline, and call it through JS.
    if (info->BreakAtEntry()) {
      DCHECK(!is_construct);
      DCHECK(new_target->IsUndefined(isolate));
      Handle<JSFunction> function;
      ASSIGN_RETURN_ON_EXCEPTION(isolate, function,
                                 ApiNatives::InstantiateFunction(
                                     info, MaybeHandle<v8::internal::Name>()),
                                 Object);
      Handle<Code> trampoline = BUILTIN_CODE(isolate, DebugBreakTrampoline);
      function->set_code(*trampoline);
      return Execution::Call(isolate, function, receiver, argc, args);
    }
  }

  Handle<FunctionTemplateInfo> fun_data =
      function->IsFunctionTemplateInfo()
          ? Handle<FunctionTemplateInfo>::cast(function)
          : handle(JSFunction::cast(*function)->shared()->get_api_func_data(),
                   isolate);
  // Construct BuiltinArguments object:
  // new target, function, arguments reversed, receiver.
  const int kBufferSize = 32;
  Address small_argv[kBufferSize];
  Address* argv;
  const int frame_argc = argc + BuiltinArguments::kNumExtraArgsWithReceiver;
  if (frame_argc <= kBufferSize) {
    argv = small_argv;
  } else {
    argv = new Address[frame_argc];
  }
  int cursor = frame_argc - 1;
  argv[cursor--] = receiver->ptr();
  for (int i = 0; i < argc; ++i) {
    argv[cursor--] = args[i]->ptr();
  }
  DCHECK_EQ(cursor, BuiltinArguments::kPaddingOffset);
  argv[BuiltinArguments::kPaddingOffset] =
      ReadOnlyRoots(isolate).the_hole_value()->ptr();
  argv[BuiltinArguments::kArgcOffset] = Smi::FromInt(frame_argc)->ptr();
  argv[BuiltinArguments::kTargetOffset] = function->ptr();
  argv[BuiltinArguments::kNewTargetOffset] = new_target->ptr();
  MaybeHandle<Object> result;
  {
    RelocatableArguments arguments(isolate, frame_argc, &argv[frame_argc - 1]);
    if (is_construct) {
      result = HandleApiCallHelper<true>(isolate, function, new_target,
                                         fun_data, receiver, arguments);
    } else {
      result = HandleApiCallHelper<false>(isolate, function, new_target,
                                          fun_data, receiver, arguments);
    }
  }
  if (argv != small_argv) delete[] argv;
  return result;
}

// Helper function to handle calls to non-function objects created through the
// API. The object can be called as either a constructor (using new) or just as
// a function (without new).
V8_WARN_UNUSED_RESULT static Object* HandleApiCallAsFunctionOrConstructor(
    Isolate* isolate, bool is_construct_call, BuiltinArguments args) {
  Handle<Object> receiver = args.receiver();

  // Get the object called.
  JSObject obj = JSObject::cast(*receiver);

  // Set the new target.
  HeapObject new_target;
  if (is_construct_call) {
    // TODO(adamk): This should be passed through in args instead of
    // being patched in here. We need to set a non-undefined value
    // for v8::FunctionCallbackInfo::IsConstructCall() to get the
    // right answer.
    new_target = obj;
  } else {
    new_target = ReadOnlyRoots(isolate).undefined_value();
  }

  // Get the invocation callback from the function descriptor that was
  // used to create the called object.
  DCHECK(obj->map()->is_callable());
  JSFunction constructor = JSFunction::cast(obj->map()->GetConstructor());
  DCHECK(constructor->shared()->IsApiFunction());
  Object* handler =
      constructor->shared()->get_api_func_data()->GetInstanceCallHandler();
  DCHECK(!handler->IsUndefined(isolate));
  CallHandlerInfo call_data = CallHandlerInfo::cast(handler);

  // Get the data for the call and perform the callback.
  Object* result;
  {
    HandleScope scope(isolate);
    LOG(isolate, ApiObjectAccess("call non-function", obj));
    FunctionCallbackArguments custom(isolate, call_data->data(), constructor,
                                     obj, new_target, args.address_of_arg_at(1),
                                     args.length() - 1);
    Handle<Object> result_handle = custom.Call(call_data);
    if (result_handle.is_null()) {
      result = ReadOnlyRoots(isolate).undefined_value();
    } else {
      result = *result_handle;
    }
  }
  // Check for exceptions and return result.
  RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
  return result;
}

// Handle calls to non-function objects created through the API. This delegate
// function is used when the call is a normal function call.
BUILTIN(HandleApiCallAsFunction) {
  return HandleApiCallAsFunctionOrConstructor(isolate, false, args);
}

// Handle calls to non-function objects created through the API. This delegate
// function is used when the call is a construct call.
BUILTIN(HandleApiCallAsConstructor) {
  return HandleApiCallAsFunctionOrConstructor(isolate, true, args);
}

}  // namespace internal
}  // namespace v8
