// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/bootstrap_natives.h"

#include "lib/invocation_mirror.h"
#include "vm/code_patcher.h"
#include "vm/exceptions.h"
#include "vm/heap/heap.h"
#include "vm/native_entry.h"
#include "vm/object.h"
#include "vm/object_store.h"
#include "vm/resolver.h"
#include "vm/stack_frame.h"
#include "vm/symbols.h"

namespace dart {

DEFINE_NATIVE_ENTRY(DartAsync_fatal, 0, 1) {
  // The dart:async library code entered an unrecoverable state.
  const Instance& instance =
      Instance::CheckedHandle(zone, arguments->NativeArgAt(0));
  const char* msg = instance.ToCString();
  OS::PrintErr("Fatal error in dart:async: %s\n", msg);
  FATAL("%s", msg);
  return Object::null();
}

DEFINE_NATIVE_ENTRY(Object_equals, 0, 1) {
  // Implemented in the flow graph builder.
  UNREACHABLE();
  return Object::null();
}

static intptr_t GetHash(Isolate* isolate, const ObjectPtr obj) {
#if defined(HASH_IN_OBJECT_HEADER)
  return Object::GetCachedHash(obj);
#else
  Heap* heap = isolate->group()->heap();
  ASSERT(obj->IsDartInstance());
  return heap->GetHash(obj);
#endif
}

DEFINE_NATIVE_ENTRY(Object_getHash, 0, 1) {
  // Please note that no handle is created for the argument.
  // This is safe since the argument is only used in a tail call.
  // The performance benefit is more than 5% when using hashCode.
  return Smi::New(GetHash(isolate, arguments->NativeArgAt(0)));
}

DEFINE_NATIVE_ENTRY(Object_setHashIfNotSetYet, 0, 2) {
  GET_NON_NULL_NATIVE_ARGUMENT(Smi, hash, arguments->NativeArgAt(1));
#if defined(HASH_IN_OBJECT_HEADER)
  return Smi::New(
      Object::SetCachedHashIfNotSet(arguments->NativeArgAt(0), hash.Value()));
#else
  const Instance& instance =
      Instance::CheckedHandle(zone, arguments->NativeArgAt(0));
  Heap* heap = thread->heap();
  return Smi::New(heap->SetHashIfNotSet(instance.ptr(), hash.Value()));
#endif
}

DEFINE_NATIVE_ENTRY(Object_toString, 0, 1) {
  const Instance& instance =
      Instance::CheckedHandle(zone, arguments->NativeArgAt(0));
  if (instance.IsString()) {
    return instance.ptr();
  }
  if (instance.IsAbstractType()) {
    return AbstractType::Cast(instance).UserVisibleName();
  }
  const char* c_str = instance.ToCString();
  return String::New(c_str);
}

DEFINE_NATIVE_ENTRY(Object_runtimeType, 0, 1) {
  const Instance& instance =
      Instance::CheckedHandle(zone, arguments->NativeArgAt(0));
  if (instance.IsString()) {
    return Type::StringType();
  } else if (instance.IsInteger()) {
    return Type::IntType();
  } else if (instance.IsDouble()) {
    return Type::Double();
  } else if (instance.IsType() || instance.IsFunctionType()) {
    return Type::DartTypeType();
  }
  return instance.GetType(Heap::kNew);
}

static bool HaveSameRuntimeTypeHelper(Zone* zone,
                                      const Instance& left,
                                      const Instance& right) {
  const intptr_t left_cid = left.GetClassId();
  const intptr_t right_cid = right.GetClassId();

  if (left_cid != right_cid) {
    if (IsIntegerClassId(left_cid)) {
      return IsIntegerClassId(right_cid);
    }
    if (IsStringClassId(left_cid)) {
      return IsStringClassId(right_cid);
    }
    if (IsTypeClassId(left_cid)) {
      return IsTypeClassId(right_cid);
    }
    return false;
  }

  if (left_cid == kClosureCid) {
    const auto& left_closure = Closure::Cast(left);
    const auto& right_closure = Closure::Cast(right);
    // If all the components that make up the instantiated signature are equal,
    // then no need to instantiate.
    if (left_closure.function_type_arguments() ==
            right_closure.function_type_arguments() &&
        left_closure.delayed_type_arguments() ==
            right_closure.delayed_type_arguments() &&
        left_closure.instantiator_type_arguments() ==
            right_closure.instantiator_type_arguments()) {
      const auto& left_fun = Function::Handle(zone, left_closure.function());
      const auto& right_fun = Function::Handle(zone, right_closure.function());
      if (left_fun.signature() == right_fun.signature()) {
        return true;
      }
    }
    const AbstractType& left_type =
        AbstractType::Handle(zone, left.GetType(Heap::kNew));
    const AbstractType& right_type =
        AbstractType::Handle(zone, right.GetType(Heap::kNew));
    return left_type.IsEquivalent(right_type, TypeEquality::kSyntactical);
  }

  const Class& cls = Class::Handle(zone, left.clazz());
  if (!cls.IsGeneric()) {
    return true;
  }

  if (left.GetTypeArguments() == right.GetTypeArguments()) {
    return true;
  }
  const TypeArguments& left_type_arguments =
      TypeArguments::Handle(zone, left.GetTypeArguments());
  const TypeArguments& right_type_arguments =
      TypeArguments::Handle(zone, right.GetTypeArguments());
  const intptr_t num_type_args = cls.NumTypeArguments();
  const intptr_t num_type_params = cls.NumTypeParameters();
  return left_type_arguments.IsSubvectorEquivalent(
      right_type_arguments, num_type_args - num_type_params, num_type_params,
      TypeEquality::kSyntactical);
}

DEFINE_NATIVE_ENTRY(Object_haveSameRuntimeType, 0, 2) {
  const Instance& left =
      Instance::CheckedHandle(zone, arguments->NativeArgAt(0));
  const Instance& right =
      Instance::CheckedHandle(zone, arguments->NativeArgAt(1));
  return Bool::Get(HaveSameRuntimeTypeHelper(zone, left, right)).ptr();
}

DEFINE_NATIVE_ENTRY(Object_instanceOf, 0, 4) {
  const Instance& instance =
      Instance::CheckedHandle(zone, arguments->NativeArgAt(0));
  const TypeArguments& instantiator_type_arguments =
      TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(1));
  const TypeArguments& function_type_arguments =
      TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(2));
  const AbstractType& type =
      AbstractType::CheckedHandle(zone, arguments->NativeArgAt(3));
  ASSERT(type.IsFinalized());
  const bool is_instance_of = instance.IsInstanceOf(
      type, instantiator_type_arguments, function_type_arguments);
  if (FLAG_trace_type_checks) {
    const char* result_str = is_instance_of ? "true" : "false";
    OS::PrintErr("Native Object.instanceOf: result %s\n", result_str);
    const AbstractType& instance_type =
        AbstractType::Handle(zone, instance.GetType(Heap::kNew));
    OS::PrintErr("  instance type: %s\n",
                 String::Handle(zone, instance_type.Name()).ToCString());
    OS::PrintErr("  test type: %s\n",
                 String::Handle(zone, type.Name()).ToCString());
  }
  return Bool::Get(is_instance_of).ptr();
}

DEFINE_NATIVE_ENTRY(Object_simpleInstanceOf, 0, 2) {
  // This native is only called when the right hand side passes
  // SimpleInstanceOfType and it is a non-negative test.
  const Instance& instance =
      Instance::CheckedHandle(zone, arguments->NativeArgAt(0));
  const AbstractType& type =
      AbstractType::CheckedHandle(zone, arguments->NativeArgAt(1));
  ASSERT(type.IsFinalized());
  ASSERT(type.IsInstantiated());
  const bool is_instance_of = instance.IsInstanceOf(
      type, Object::null_type_arguments(), Object::null_type_arguments());
  return Bool::Get(is_instance_of).ptr();
}

DEFINE_NATIVE_ENTRY(AbstractType_toString, 0, 1) {
  const AbstractType& type =
      AbstractType::CheckedHandle(zone, arguments->NativeArgAt(0));
  return type.UserVisibleName();
}

DEFINE_NATIVE_ENTRY(Type_getHashCode, 0, 1) {
  const Type& type = Type::CheckedHandle(zone, arguments->NativeArgAt(0));
  intptr_t hash_val = type.Hash();
  ASSERT(hash_val > 0);
  ASSERT(Smi::IsValid(hash_val));
  return Smi::New(hash_val);
}

DEFINE_NATIVE_ENTRY(Type_equality, 0, 2) {
  const Type& type = Type::CheckedHandle(zone, arguments->NativeArgAt(0));
  const Instance& other =
      Instance::CheckedHandle(zone, arguments->NativeArgAt(1));
  if (type.ptr() == other.ptr()) {
    return Bool::True().ptr();
  }
  return Bool::Get(type.IsEquivalent(other, TypeEquality::kSyntactical)).ptr();
}

DEFINE_NATIVE_ENTRY(FunctionType_getHashCode, 0, 1) {
  const FunctionType& type =
      FunctionType::CheckedHandle(zone, arguments->NativeArgAt(0));
  intptr_t hash_val = type.Hash();
  ASSERT(hash_val > 0);
  ASSERT(Smi::IsValid(hash_val));
  return Smi::New(hash_val);
}

DEFINE_NATIVE_ENTRY(FunctionType_equality, 0, 2) {
  const FunctionType& type =
      FunctionType::CheckedHandle(zone, arguments->NativeArgAt(0));
  const Instance& other =
      Instance::CheckedHandle(zone, arguments->NativeArgAt(1));
  if (type.ptr() == other.ptr()) {
    return Bool::True().ptr();
  }
  return Bool::Get(type.IsEquivalent(other, TypeEquality::kSyntactical)).ptr();
}

DEFINE_NATIVE_ENTRY(LibraryPrefix_isLoaded, 0, 1) {
  const LibraryPrefix& prefix =
      LibraryPrefix::CheckedHandle(zone, arguments->NativeArgAt(0));
  return Bool::Get(isolate->IsPrefixLoaded(prefix)).ptr();
}

DEFINE_NATIVE_ENTRY(LibraryPrefix_setLoaded, 0, 1) {
  const LibraryPrefix& prefix =
      LibraryPrefix::CheckedHandle(zone, arguments->NativeArgAt(0));
  isolate->SetPrefixIsLoaded(prefix);
  return Instance::null();
}

DEFINE_NATIVE_ENTRY(LibraryPrefix_loadingUnit, 0, 1) {
  const LibraryPrefix& prefix =
      LibraryPrefix::CheckedHandle(zone, arguments->NativeArgAt(0));
  const Library& target = Library::Handle(zone, prefix.GetLibrary(0));
  const LoadingUnit& unit = LoadingUnit::Handle(zone, target.loading_unit());
  return Smi::New(unit.IsNull() ? LoadingUnit::kIllegalId : unit.id());
}

DEFINE_NATIVE_ENTRY(LibraryPrefix_issueLoad, 0, 1) {
  const Smi& id = Smi::CheckedHandle(zone, arguments->NativeArgAt(0));
  Array& units =
      Array::Handle(zone, isolate->group()->object_store()->loading_units());
  if (units.IsNull()) {
    // Not actually split.
    const Library& lib = Library::Handle(zone, Library::CoreLibrary());
    const String& sel = String::Handle(zone, String::New("_completeLoads"));
    const Function& func =
        Function::Handle(zone, lib.LookupFunctionAllowPrivate(sel));
    ASSERT(!func.IsNull());
    const Array& args = Array::Handle(zone, Array::New(3));
    args.SetAt(0, id);
    args.SetAt(1, String::Handle(zone));
    args.SetAt(2, Bool::Get(false));
    return DartEntry::InvokeFunction(func, args);
  }
  ASSERT(id.Value() != LoadingUnit::kIllegalId);
  LoadingUnit& unit = LoadingUnit::Handle(zone);
  unit ^= units.At(id.Value());
  return unit.IssueLoad();
}

DEFINE_NATIVE_ENTRY(Internal_has63BitSmis, 0, 0) {
#if defined(ARCH_IS_64_BIT) && !defined(DART_COMPRESSED_POINTERS)
  return Bool::True().ptr();
#else
  return Bool::False().ptr();
#endif  // defined(ARCH_IS_64_BIT)
}

DEFINE_NATIVE_ENTRY(Internal_unsafeCast, 0, 1) {
  UNREACHABLE();  // Should be erased at Kernel translation time.
  return arguments->NativeArgAt(0);
}

DEFINE_NATIVE_ENTRY(Internal_nativeEffect, 0, 1) {
  UNREACHABLE();
}

DEFINE_NATIVE_ENTRY(Internal_reachabilityFence, 0, 1) {
  UNREACHABLE();
}

DEFINE_NATIVE_ENTRY(Internal_collectAllGarbage, 0, 0) {
  isolate->group()->heap()->CollectAllGarbage();
  return Object::null();
}

DEFINE_NATIVE_ENTRY(Internal_deoptimizeFunctionsOnStack, 0, 0) {
  DeoptimizeFunctionsOnStack();
  return Object::null();
}

static bool ExtractInterfaceTypeArgs(Zone* zone,
                                     const Class& instance_cls,
                                     const TypeArguments& instance_type_args,
                                     const Class& interface_cls,
                                     TypeArguments* interface_type_args) {
  Class& cur_cls = Class::Handle(zone, instance_cls.ptr());
  // The following code is a specialization of Class::IsSubtypeOf().
  Array& interfaces = Array::Handle(zone);
  AbstractType& interface = AbstractType::Handle(zone);
  Class& cur_interface_cls = Class::Handle(zone);
  TypeArguments& cur_interface_type_args = TypeArguments::Handle(zone);
  while (true) {
    // Additional subtyping rules related to 'FutureOr' are not applied.
    if (cur_cls.ptr() == interface_cls.ptr()) {
      *interface_type_args = instance_type_args.ptr();
      return true;
    }
    interfaces = cur_cls.interfaces();
    for (intptr_t i = 0; i < interfaces.Length(); i++) {
      interface ^= interfaces.At(i);
      ASSERT(interface.IsFinalized());
      cur_interface_cls = interface.type_class();
      cur_interface_type_args = interface.arguments();
      if (!cur_interface_type_args.IsNull() &&
          !cur_interface_type_args.IsInstantiated()) {
        cur_interface_type_args = cur_interface_type_args.InstantiateFrom(
            instance_type_args, Object::null_type_arguments(), kNoneFree,
            Heap::kNew);
      }
      if (ExtractInterfaceTypeArgs(zone, cur_interface_cls,
                                   cur_interface_type_args, interface_cls,
                                   interface_type_args)) {
        return true;
      }
    }
    cur_cls = cur_cls.SuperClass();
    if (cur_cls.IsNull()) {
      return false;
    }
  }
}

// for documentation see pkg/dart_internal/lib/extract_type_arguments.dart
DEFINE_NATIVE_ENTRY(Internal_extractTypeArguments, 0, 2) {
  const Instance& instance =
      Instance::CheckedHandle(zone, arguments->NativeArgAt(0));
  const Instance& extract =
      Instance::CheckedHandle(zone, arguments->NativeArgAt(1));

  Class& interface_cls = Class::Handle(zone);
  intptr_t num_type_args = 0;
  if (arguments->NativeTypeArgCount() >= 1) {
    const AbstractType& function_type_arg =
        AbstractType::Handle(zone, arguments->NativeTypeArgAt(0));
    if (function_type_arg.IsType() &&
        (function_type_arg.arguments() == TypeArguments::null())) {
      interface_cls = function_type_arg.type_class();
      num_type_args = interface_cls.NumTypeParameters();
    }
  }
  if (num_type_args == 0) {
    Exceptions::ThrowArgumentError(String::Handle(
        zone,
        String::New(
            "single function type argument must specify a generic class")));
  }
  if (instance.IsNull()) {
    Exceptions::ThrowArgumentError(instance);
  }
  // Function 'extract' must be generic and accept the same number of type args,
  // unless we execute Dart 1.0 code.
  if (extract.IsNull() || !extract.IsClosure() ||
      ((num_type_args > 0) &&  // Dart 1.0 if num_type_args == 0.
       (Function::Handle(zone, Closure::Cast(extract).function())
            .NumTypeParameters() != num_type_args))) {
    Exceptions::ThrowArgumentError(String::Handle(
        zone,
        String::New("argument 'extract' is not a generic function or not one "
                    "accepting the correct number of type arguments")));
  }
  TypeArguments& extracted_type_args = TypeArguments::Handle(zone);
  if (num_type_args > 0) {
    // The passed instance must implement interface_cls.
    TypeArguments& interface_type_args = TypeArguments::Handle(zone);
    interface_type_args = TypeArguments::New(num_type_args);
    Class& instance_cls = Class::Handle(zone, instance.clazz());
    TypeArguments& instance_type_args = TypeArguments::Handle(zone);
    if (instance_cls.NumTypeArguments() > 0) {
      instance_type_args = instance.GetTypeArguments();
    }
    if (!ExtractInterfaceTypeArgs(zone, instance_cls, instance_type_args,
                                  interface_cls, &interface_type_args)) {
      Exceptions::ThrowArgumentError(String::Handle(
          zone, String::New("type of argument 'instance' is not a subtype of "
                            "the function type argument")));
    }
    if (!interface_type_args.IsNull()) {
      extracted_type_args = TypeArguments::New(num_type_args);
      const intptr_t offset = interface_cls.NumTypeArguments() - num_type_args;
      AbstractType& type_arg = AbstractType::Handle(zone);
      for (intptr_t i = 0; i < num_type_args; i++) {
        type_arg = interface_type_args.TypeAt(offset + i);
        extracted_type_args.SetTypeAt(i, type_arg);
      }
      extracted_type_args =
          extracted_type_args.Canonicalize(thread, nullptr);  // Can be null.
    }
  }
  // Call the closure 'extract'.
  Array& args_desc = Array::Handle(zone);
  Array& args = Array::Handle(zone);
  if (extracted_type_args.IsNull()) {
    args_desc = ArgumentsDescriptor::NewBoxed(0, 1);
    args = Array::New(1);
    args.SetAt(0, extract);
  } else {
    args_desc = ArgumentsDescriptor::NewBoxed(num_type_args, 1);
    args = Array::New(2);
    args.SetAt(0, extracted_type_args);
    args.SetAt(1, extract);
  }
  const Object& result =
      Object::Handle(zone, DartEntry::InvokeClosure(thread, args, args_desc));
  if (result.IsError()) {
    Exceptions::PropagateError(Error::Cast(result));
    UNREACHABLE();
  }
  return result.ptr();
}

DEFINE_NATIVE_ENTRY(Internal_prependTypeArguments, 0, 4) {
  const TypeArguments& function_type_arguments =
      TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0));
  const TypeArguments& parent_type_arguments =
      TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(1));
  GET_NON_NULL_NATIVE_ARGUMENT(Smi, smi_parent_len, arguments->NativeArgAt(2));
  GET_NON_NULL_NATIVE_ARGUMENT(Smi, smi_len, arguments->NativeArgAt(3));
  return function_type_arguments.Prepend(
      zone, parent_type_arguments, smi_parent_len.Value(), smi_len.Value());
}

// Check that a set of type arguments satisfy the type parameter bounds on a
// closure.
// Arg0: Closure object
// Arg1: Type arguments to function
DEFINE_NATIVE_ENTRY(Internal_boundsCheckForPartialInstantiation, 0, 2) {
  const Closure& closure =
      Closure::CheckedHandle(zone, arguments->NativeArgAt(0));
  const Function& target = Function::Handle(zone, closure.function());
  ASSERT(target.IsGeneric());  // No need to check bounds for non-generics.
  const TypeParameters& type_params =
      TypeParameters::Handle(zone, target.type_parameters());
  if (type_params.IsNull() || type_params.AllDynamicBounds()) {
    // The function is not generic or the bounds are all dynamic.
    return Object::null();
  }

  const TypeArguments& type_args_to_check =
      TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(1));

  // This should be guaranteed by the front-end.
  ASSERT(type_args_to_check.IsNull() ||
         type_params.Length() <= type_args_to_check.Length());

  // The bounds on the closure may need instantiation.
  const TypeArguments& instantiator_type_args =
      TypeArguments::Handle(zone, closure.instantiator_type_arguments());
  const TypeArguments& function_type_args =
      TypeArguments::Handle(zone, closure.function_type_arguments());

  AbstractType& supertype = AbstractType::Handle(zone);
  AbstractType& subtype = AbstractType::Handle(zone);
  for (intptr_t i = 0; i < type_params.Length(); ++i) {
    supertype = type_params.BoundAt(i);
    subtype = type_args_to_check.IsNull() ? Object::dynamic_type().ptr()
                                          : type_args_to_check.TypeAt(i);

    ASSERT(!subtype.IsNull());
    ASSERT(!supertype.IsNull());

    // The supertype may not be instantiated.
    if (!AbstractType::InstantiateAndTestSubtype(
            &subtype, &supertype, instantiator_type_args, function_type_args)) {
      // Throw a dynamic type error.
      TokenPosition location = TokenPosition::kNoSource;
      {
        DartFrameIterator iterator(Thread::Current(),
                                   StackFrameIterator::kNoCrossThreadIteration);
        StackFrame* caller_frame = iterator.NextFrame();
        ASSERT(caller_frame != NULL);
        location = caller_frame->GetTokenPos();
      }
      const auto& parameter_name = String::Handle(zone, type_params.NameAt(i));
      Exceptions::CreateAndThrowTypeError(location, subtype, supertype,
                                          parameter_name);
      UNREACHABLE();
    }
  }

  return Object::null();
}

DEFINE_NATIVE_ENTRY(InvocationMirror_unpackTypeArguments, 0, 2) {
  const TypeArguments& type_arguments =
      TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0));
  const Smi& num_type_arguments =
      Smi::CheckedHandle(zone, arguments->NativeArgAt(1));
  bool all_dynamic = type_arguments.IsNull();
  const intptr_t len =
      all_dynamic ? num_type_arguments.Value() : type_arguments.Length();
  const Array& type_list = Array::Handle(
      zone, Array::New(len, Type::Handle(zone, Type::DartTypeType())));
  AbstractType& type = AbstractType::Handle(zone);
  for (intptr_t i = 0; i < len; i++) {
    if (all_dynamic) {
      type_list.SetAt(i, Object::dynamic_type());
    } else {
      type = type_arguments.TypeAt(i);
      type_list.SetAt(i, type);
    }
  }
  type_list.MakeImmutable();
  return type_list.ptr();
}

DEFINE_NATIVE_ENTRY(NoSuchMethodError_existingMethodSignature, 0, 3) {
  const Instance& receiver =
      Instance::CheckedHandle(zone, arguments->NativeArgAt(0));
  GET_NON_NULL_NATIVE_ARGUMENT(String, method_name, arguments->NativeArgAt(1));
  GET_NON_NULL_NATIVE_ARGUMENT(Smi, invocation_type, arguments->NativeArgAt(2));
  InvocationMirror::Level level;
  InvocationMirror::Kind kind;
  InvocationMirror::DecodeType(invocation_type.Value(), &level, &kind);

  Function& function = Function::Handle(zone);
  if (receiver.IsType()) {
    const auto& cls = Class::Handle(zone, Type::Cast(receiver).type_class());
    const auto& error = Error::Handle(zone, cls.EnsureIsFinalized(thread));
    if (!error.IsNull()) {
      Exceptions::PropagateError(error);
      UNREACHABLE();
    }
    if (level == InvocationMirror::kConstructor) {
      function = cls.LookupConstructor(method_name);
      if (function.IsNull()) {
        function = cls.LookupFactory(method_name);
      }
    } else {
      function = cls.LookupStaticFunction(method_name);
    }
  } else if (receiver.IsClosure()) {
    function = Closure::Cast(receiver).function();
  } else {
    auto& cls = Class::Handle(zone, receiver.clazz());
    if (level == InvocationMirror::kSuper) {
      cls = cls.SuperClass();
    }
    function = Resolver::ResolveDynamicAnyArgs(zone, cls, method_name,
                                               /*allow_add=*/false);
  }
  if (!function.IsNull()) {
    return function.UserVisibleSignature();
  }
  return String::null();
}

}  // namespace dart
