// Copyright (c) 2013, 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 "include/dart_api.h"
#include "include/dart_native_api.h"

#include <memory>
#include <utility>

#include "lib/stacktrace.h"
#include "platform/assert.h"
#include "vm/class_finalizer.h"
#include "vm/clustered_snapshot.h"
#include "vm/compilation_trace.h"
#include "vm/compiler/jit/compiler.h"
#include "vm/dart.h"
#include "vm/dart_api_impl.h"
#include "vm/dart_api_message.h"
#include "vm/dart_api_state.h"
#include "vm/dart_entry.h"
#include "vm/debugger.h"
#include "vm/dwarf.h"
#include "vm/elf.h"
#include "platform/unicode.h"
#include "vm/exceptions.h"
#include "vm/flags.h"
#include "vm/growable_array.h"
#include "vm/heap/verifier.h"
#include "vm/image_snapshot.h"
#include "vm/isolate_reload.h"
#include "vm/kernel_isolate.h"
#include "vm/lockers.h"
#include "vm/message.h"
#include "vm/message_handler.h"
#include "vm/native_entry.h"
#include "vm/native_symbol.h"
#include "vm/object.h"
#include "vm/object_store.h"
#include "vm/os.h"
#include "vm/os_thread.h"
#include "vm/port.h"
#include "vm/profiler.h"
#include "vm/profiler_service.h"
#include "vm/program_visitor.h"
#include "vm/resolver.h"
#include "vm/reusable_handles.h"
#include "vm/service.h"
#include "vm/service_event.h"
#include "vm/service_isolate.h"
#include "vm/stack_frame.h"
#include "vm/symbols.h"
#include "vm/tags.h"
#include "vm/thread_registry.h"
#include "vm/uri.h"
#include "vm/version.h"

#if !defined(DART_PRECOMPILED_RUNTIME)
#include "vm/compiler/aot/precompiler.h"
#include "vm/kernel_loader.h"
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

namespace dart {

// Facilitate quick access to the current zone once we have the current thread.
#define Z (T->zone())

DECLARE_FLAG(bool, print_class_table);
DECLARE_FLAG(bool, verify_handles);
#if defined(DEBUG) && !defined(DART_PRECOMPILED_RUNTIME)
DEFINE_FLAG(bool,
            check_function_fingerprints,
            true,
            "Check function fingerprints");
#endif  // defined(DEBUG) && !defined(DART_PRECOMPILED_RUNTIME).
DEFINE_FLAG(bool,
            verify_acquired_data,
            false,
            "Verify correct API acquire/release of typed data.");
DEFINE_FLAG(bool,
            dump_tables,
            false,
            "Dump common hash tables before snapshotting.");

#define CHECK_ERROR_HANDLE(error)                                              \
  {                                                                            \
    ErrorPtr err = (error);                                                    \
    if (err != Error::null()) {                                                \
      return Api::NewHandle(T, err);                                           \
    }                                                                          \
  }

ThreadLocalKey Api::api_native_key_ = kUnsetThreadLocalKey;
Dart_Handle Api::true_handle_ = NULL;
Dart_Handle Api::false_handle_ = NULL;
Dart_Handle Api::null_handle_ = NULL;
Dart_Handle Api::empty_string_handle_ = NULL;

const char* CanonicalFunction(const char* func) {
  if (strncmp(func, "dart::", 6) == 0) {
    return func + 6;
  } else {
    return func;
  }
}

#if defined(DEBUG)
// An object visitor which will iterate over all the function objects in the
// heap and check if the result type and parameter types are canonicalized
// or not. An assertion is raised if a type is not canonicalized.
class CheckFunctionTypesVisitor : public ObjectVisitor {
 public:
  explicit CheckFunctionTypesVisitor(Thread* thread)
      : classHandle_(Class::Handle(thread->zone())),
        funcHandle_(Function::Handle(thread->zone())),
        typeHandle_(AbstractType::Handle(thread->zone())) {}

  void VisitObject(ObjectPtr obj) {
    if (obj->IsFunction()) {
      funcHandle_ ^= obj;
      classHandle_ ^= funcHandle_.Owner();
      // Signature functions get created, but not canonicalized, when function
      // types get instantiated during run time type tests.
      if (funcHandle_.IsSignatureFunction()) {
        return;
      }
      // Verify that the result type of a function is canonical or a
      // TypeParameter.
      typeHandle_ ^= funcHandle_.result_type();
      ASSERT(typeHandle_.IsTypeParameter() || typeHandle_.IsCanonical());
      // Verify that the types in the function signature are all canonical or
      // a TypeParameter.
      const intptr_t num_parameters = funcHandle_.NumParameters();
      for (intptr_t i = 0; i < num_parameters; i++) {
        typeHandle_ = funcHandle_.ParameterTypeAt(i);
        ASSERT(typeHandle_.IsTypeParameter() || typeHandle_.IsCanonical());
      }
    }
  }

 private:
  Class& classHandle_;
  Function& funcHandle_;
  AbstractType& typeHandle_;
};
#endif  // #if defined(DEBUG).

static InstancePtr GetListInstance(Zone* zone, const Object& obj) {
  if (obj.IsInstance()) {
    ObjectStore* object_store = Isolate::Current()->object_store();
    Type& list_rare_type =
        Type::Handle(zone, object_store->non_nullable_list_rare_type());
    if (list_rare_type.IsNull()) {
      const Library& core_lib = Library::Handle(zone, Library::CoreLibrary());
      const Class& list_class =
          Class::Handle(zone, core_lib.LookupClass(Symbols::List()));
      ASSERT(!list_class.IsNull());
      list_rare_type ^= list_class.RareType();
      object_store->set_non_nullable_list_rare_type(list_rare_type);
    }
    const Instance& instance = Instance::Cast(obj);
    const Class& obj_class = Class::Handle(zone, obj.clazz());
    if (Class::IsSubtypeOf(obj_class, Object::null_type_arguments(),
                           Nullability::kNonNullable, list_rare_type,
                           Heap::kNew)) {
      return instance.raw();
    }
  }
  return Instance::null();
}

static InstancePtr GetMapInstance(Zone* zone, const Object& obj) {
  if (obj.IsInstance()) {
    ObjectStore* object_store = Isolate::Current()->object_store();
    Type& map_rare_type =
        Type::Handle(zone, object_store->non_nullable_map_rare_type());
    if (map_rare_type.IsNull()) {
      const Library& core_lib = Library::Handle(zone, Library::CoreLibrary());
      const Class& map_class =
          Class::Handle(zone, core_lib.LookupClass(Symbols::Map()));
      ASSERT(!map_class.IsNull());
      map_rare_type ^= map_class.RareType();
      object_store->set_non_nullable_map_rare_type(map_rare_type);
    }
    const Instance& instance = Instance::Cast(obj);
    const Class& obj_class = Class::Handle(zone, obj.clazz());
    if (Class::IsSubtypeOf(obj_class, Object::null_type_arguments(),
                           Nullability::kNonNullable, map_rare_type,
                           Heap::kNew)) {
      return instance.raw();
    }
  }
  return Instance::null();
}

static bool IsCompiletimeErrorObject(Zone* zone, const Object& obj) {
#if defined(DART_PRECOMPILED_RUNTIME)
  // All compile-time errors were handled at snapshot generation time and
  // compiletime_error_class was removed.
  return false;
#else
  Isolate* I = Thread::Current()->isolate();
  const Class& error_class =
      Class::Handle(zone, I->object_store()->compiletime_error_class());
  ASSERT(!error_class.IsNull());
  return (obj.GetClassId() == error_class.id());
#endif
}

static bool GetNativeStringArgument(NativeArguments* arguments,
                                    int arg_index,
                                    Dart_Handle* str,
                                    void** peer) {
  ASSERT(peer != NULL);
  if (Api::StringGetPeerHelper(arguments, arg_index, peer)) {
    *str = NULL;
    return true;
  }
  Thread* thread = arguments->thread();
  ASSERT(thread == Thread::Current());
  *peer = NULL;
  REUSABLE_OBJECT_HANDLESCOPE(thread);
  Object& obj = thread->ObjectHandle();
  obj = arguments->NativeArgAt(arg_index);
  if (IsStringClassId(obj.GetClassId())) {
    ASSERT(thread->api_top_scope() != NULL);
    *str = Api::NewHandle(thread, obj.raw());
    return true;
  }
  if (obj.IsNull()) {
    *str = Api::Null();
    return true;
  }
  return false;
}

static bool GetNativeIntegerArgument(NativeArguments* arguments,
                                     int arg_index,
                                     int64_t* value) {
  ASSERT(value != NULL);
  return Api::GetNativeIntegerArgument(arguments, arg_index, value);
}

static bool GetNativeUnsignedIntegerArgument(NativeArguments* arguments,
                                             int arg_index,
                                             uint64_t* value) {
  ASSERT(value != NULL);
  int64_t arg_value = 0;
  if (Api::GetNativeIntegerArgument(arguments, arg_index, &arg_value)) {
    *value = static_cast<uint64_t>(arg_value);
    return true;
  }
  return false;
}

static bool GetNativeDoubleArgument(NativeArguments* arguments,
                                    int arg_index,
                                    double* value) {
  ASSERT(value != NULL);
  return Api::GetNativeDoubleArgument(arguments, arg_index, value);
}

static Dart_Handle GetNativeFieldsOfArgument(NativeArguments* arguments,
                                             int arg_index,
                                             int num_fields,
                                             intptr_t* field_values,
                                             const char* current_func) {
  ASSERT(field_values != NULL);
  if (Api::GetNativeFieldsOfArgument(arguments, arg_index, num_fields,
                                     field_values)) {
    return Api::Success();
  }
  Thread* thread = arguments->thread();
  ASSERT(thread == Thread::Current());
  REUSABLE_OBJECT_HANDLESCOPE(thread);
  Object& obj = thread->ObjectHandle();
  obj = arguments->NativeArgAt(arg_index);
  if (obj.IsNull()) {
    memset(field_values, 0, (num_fields * sizeof(field_values[0])));
    return Api::Success();
  }
  // We did not succeed in extracting the native fields report the
  // appropriate error.
  if (!obj.IsInstance()) {
    return Api::NewError(
        "%s expects argument at index '%d' to be of"
        " type Instance.",
        current_func, arg_index);
  }
  const Instance& instance = Instance::Cast(obj);
  int field_count = instance.NumNativeFields();
  ASSERT(num_fields != field_count);
  return Api::NewError("%s: expected %d 'num_fields' but was passed in %d.",
                       current_func, field_count, num_fields);
}

static ObjectPtr Send0Arg(const Instance& receiver, const String& selector) {
  const intptr_t kTypeArgsLen = 0;
  const intptr_t kNumArgs = 1;
  ArgumentsDescriptor args_desc(
      Array::Handle(ArgumentsDescriptor::NewBoxed(kTypeArgsLen, kNumArgs)));
  const Function& function =
      Function::Handle(Resolver::ResolveDynamic(receiver, selector, args_desc));
  if (function.IsNull()) {
    return ApiError::New(String::Handle(String::New("")));
  }
  const Array& args = Array::Handle(Array::New(kNumArgs));
  args.SetAt(0, receiver);
  return DartEntry::InvokeFunction(function, args);
}

static ObjectPtr Send1Arg(const Instance& receiver,
                          const String& selector,
                          const Instance& argument) {
  const intptr_t kTypeArgsLen = 0;
  const intptr_t kNumArgs = 2;
  ArgumentsDescriptor args_desc(
      Array::Handle(ArgumentsDescriptor::NewBoxed(kTypeArgsLen, kNumArgs)));
  const Function& function =
      Function::Handle(Resolver::ResolveDynamic(receiver, selector, args_desc));
  if (function.IsNull()) {
    return ApiError::New(String::Handle(String::New("")));
  }
  const Array& args = Array::Handle(Array::New(kNumArgs));
  args.SetAt(0, receiver);
  args.SetAt(1, argument);
  return DartEntry::InvokeFunction(function, args);
}

static const char* GetErrorString(Thread* thread, const Object& obj) {
  // This function requires an API scope to be present.
  if (obj.IsError()) {
    ASSERT(thread->api_top_scope() != NULL);
    const Error& error = Error::Cast(obj);
    const char* str = error.ToErrorCString();
    intptr_t len = strlen(str) + 1;
    char* str_copy = Api::TopScope(thread)->zone()->Alloc<char>(len);
    strncpy(str_copy, str, len);
    // Strip a possible trailing '\n'.
    if ((len > 1) && (str_copy[len - 2] == '\n')) {
      str_copy[len - 2] = '\0';
    }
    return str_copy;
  } else {
    return "";
  }
}

Dart_Handle Api::InitNewHandle(Thread* thread, ObjectPtr raw) {
  LocalHandles* local_handles = Api::TopScope(thread)->local_handles();
  ASSERT(local_handles != NULL);
  LocalHandle* ref = local_handles->AllocateHandle();
  ref->set_raw(raw);
  return ref->apiHandle();
}

Dart_Handle Api::NewHandle(Thread* thread, ObjectPtr raw) {
  if (raw == Object::null()) {
    return Null();
  }
  if (raw == Bool::True().raw()) {
    return True();
  }
  if (raw == Bool::False().raw()) {
    return False();
  }
  ASSERT(thread->execution_state() == Thread::kThreadInVM);
  return InitNewHandle(thread, raw);
}

ObjectPtr Api::UnwrapHandle(Dart_Handle object) {
#if defined(DEBUG)
  Thread* thread = Thread::Current();
  ASSERT(thread->execution_state() == Thread::kThreadInVM);
  ASSERT(thread->IsMutatorThread());
  ASSERT(thread->isolate() != NULL);
  ASSERT(!FLAG_verify_handles || thread->IsValidLocalHandle(object) ||
         thread->isolate()->group()->api_state()->IsActivePersistentHandle(
             reinterpret_cast<Dart_PersistentHandle>(object)) ||
         Dart::IsReadOnlyApiHandle(object));
  ASSERT(FinalizablePersistentHandle::raw_offset() == 0 &&
         PersistentHandle::raw_offset() == 0 && LocalHandle::raw_offset() == 0);
#endif
  return (reinterpret_cast<LocalHandle*>(object))->raw();
}

#define DEFINE_UNWRAP(type)                                                    \
  const type& Api::Unwrap##type##Handle(Zone* zone, Dart_Handle dart_handle) { \
    const Object& obj = Object::Handle(zone, Api::UnwrapHandle(dart_handle));  \
    if (obj.Is##type()) {                                                      \
      return type::Cast(obj);                                                  \
    }                                                                          \
    return type::Handle(zone);                                                 \
  }
CLASS_LIST_FOR_HANDLES(DEFINE_UNWRAP)
#undef DEFINE_UNWRAP

const String& Api::UnwrapStringHandle(const ReusableObjectHandleScope& reuse,
                                      Dart_Handle dart_handle) {
  Object& ref = reuse.Handle();
  ref = Api::UnwrapHandle(dart_handle);
  if (ref.IsString()) {
    return String::Cast(ref);
  }
  return Object::null_string();
}

const Instance& Api::UnwrapInstanceHandle(
    const ReusableObjectHandleScope& reuse,
    Dart_Handle dart_handle) {
  Object& ref = reuse.Handle();
  ref = Api::UnwrapHandle(dart_handle);
  if (ref.IsInstance()) {
    return Instance::Cast(ref);
  }
  return Object::null_instance();
}

Dart_Handle Api::CheckAndFinalizePendingClasses(Thread* thread) {
  Isolate* isolate = thread->isolate();
  if (!isolate->AllowClassFinalization()) {
    // Class finalization is blocked for the isolate. Do nothing.
    return Api::Success();
  }
  if (ClassFinalizer::ProcessPendingClasses()) {
    return Api::Success();
  }
  ASSERT(thread->sticky_error() != Object::null());
  return Api::NewHandle(thread, thread->sticky_error());
}

Dart_Isolate Api::CastIsolate(Isolate* isolate) {
  return reinterpret_cast<Dart_Isolate>(isolate);
}

Dart_IsolateGroup Api::CastIsolateGroup(IsolateGroup* isolate_group) {
  return reinterpret_cast<Dart_IsolateGroup>(isolate_group);
}

Dart_Handle Api::NewError(const char* format, ...) {
  Thread* T = Thread::Current();
  CHECK_API_SCOPE(T);
  CHECK_CALLBACK_STATE(T);
  // Ensure we transition safepoint state to VM if we are not already in
  // that state.
  TransitionToVM transition(T);
  HANDLESCOPE(T);

  va_list args;
  va_start(args, format);
  char* buffer = OS::VSCreate(Z, format, args);
  va_end(args);

  const String& message = String::Handle(Z, String::New(buffer));
  return Api::NewHandle(T, ApiError::New(message));
}

Dart_Handle Api::NewArgumentError(const char* format, ...) {
  Thread* T = Thread::Current();
  CHECK_API_SCOPE(T);
  CHECK_CALLBACK_STATE(T);
  // Ensure we transition safepoint state to VM if we are not already in
  // that state.
  TransitionToVM transition(T);
  HANDLESCOPE(T);

  va_list args;
  va_start(args, format);
  char* buffer = OS::VSCreate(Z, format, args);
  va_end(args);

  const String& message = String::Handle(Z, String::New(buffer));
  const Array& arguments = Array::Handle(Z, Array::New(1));
  arguments.SetAt(0, message);
  Object& error = Object::Handle(
      Z, DartLibraryCalls::InstanceCreate(
             Library::Handle(Z, Library::CoreLibrary()),
             Symbols::ArgumentError(), Symbols::Dot(), arguments));
  if (!error.IsError()) {
    error = UnhandledException::New(Instance::Cast(error), Instance::Handle());
  }
  return Api::NewHandle(T, error.raw());
}

Dart_Handle Api::AcquiredError(IsolateGroup* isolate_group) {
  ApiState* state = isolate_group->api_state();
  ASSERT(state != NULL);
  PersistentHandle* acquired_error_handle = state->AcquiredError();
  return reinterpret_cast<Dart_Handle>(acquired_error_handle);
}

bool Api::IsValid(Dart_Handle handle) {
  Isolate* isolate = Isolate::Current();
  Thread* thread = Thread::Current();
  ASSERT(thread->IsMutatorThread());
  CHECK_ISOLATE(isolate);

  // Check against all of the handles in the current isolate as well as the
  // read-only handles.
  return thread->IsValidHandle(handle) ||
         isolate->group()->api_state()->IsActivePersistentHandle(
             reinterpret_cast<Dart_PersistentHandle>(handle)) ||
         isolate->group()->api_state()->IsActiveWeakPersistentHandle(
             reinterpret_cast<Dart_WeakPersistentHandle>(handle)) ||
         Dart::IsReadOnlyApiHandle(handle) ||
         Dart::IsReadOnlyHandle(reinterpret_cast<uword>(handle));
}

ApiLocalScope* Api::TopScope(Thread* thread) {
  ASSERT(thread != NULL);
  ApiLocalScope* scope = thread->api_top_scope();
  ASSERT(scope != NULL);
  return scope;
}

void Api::Init() {
  if (api_native_key_ == kUnsetThreadLocalKey) {
    api_native_key_ = OSThread::CreateThreadLocal();
  }
  ASSERT(api_native_key_ != kUnsetThreadLocalKey);
}

static Dart_Handle InitNewReadOnlyApiHandle(ObjectPtr raw) {
  ASSERT(raw->ptr()->InVMIsolateHeap());
  LocalHandle* ref = Dart::AllocateReadOnlyApiHandle();
  ref->set_raw(raw);
  return ref->apiHandle();
}

void Api::InitHandles() {
  Isolate* isolate = Isolate::Current();
  ASSERT(isolate != NULL);
  ASSERT(isolate == Dart::vm_isolate());
  ApiState* state = isolate->group()->api_state();
  ASSERT(state != NULL);

  ASSERT(true_handle_ == NULL);
  true_handle_ = InitNewReadOnlyApiHandle(Bool::True().raw());

  ASSERT(false_handle_ == NULL);
  false_handle_ = InitNewReadOnlyApiHandle(Bool::False().raw());

  ASSERT(null_handle_ == NULL);
  null_handle_ = InitNewReadOnlyApiHandle(Object::null());

  ASSERT(empty_string_handle_ == NULL);
  empty_string_handle_ = InitNewReadOnlyApiHandle(Symbols::Empty().raw());
}

void Api::Cleanup() {
  true_handle_ = NULL;
  false_handle_ = NULL;
  null_handle_ = NULL;
  empty_string_handle_ = NULL;
}

bool Api::StringGetPeerHelper(NativeArguments* arguments,
                              int arg_index,
                              void** peer) {
  NoSafepointScope no_safepoint_scope;
  ObjectPtr raw_obj = arguments->NativeArgAt(arg_index);
  if (!raw_obj->IsHeapObject()) {
    return false;
  }
  intptr_t cid = raw_obj->GetClassId();
  if (cid == kExternalOneByteStringCid) {
    ExternalOneByteStringPtr raw_string =
        static_cast<ExternalOneByteStringPtr>(raw_obj);
    *peer = raw_string->ptr()->peer_;
    return true;
  }
  if (cid == kOneByteStringCid || cid == kTwoByteStringCid) {
    Isolate* isolate = arguments->thread()->isolate();
    *peer = isolate->heap()->GetPeer(raw_obj);
    return (*peer != 0);
  }
  if (cid == kExternalTwoByteStringCid) {
    ExternalTwoByteStringPtr raw_string =
        static_cast<ExternalTwoByteStringPtr>(raw_obj);
    *peer = raw_string->ptr()->peer_;
    return true;
  }
  return false;
}

bool Api::GetNativeReceiver(NativeArguments* arguments, intptr_t* value) {
  NoSafepointScope no_safepoint_scope;
  ObjectPtr raw_obj = arguments->NativeArg0();
  if (raw_obj->IsHeapObject()) {
    intptr_t cid = raw_obj->GetClassId();
    if (cid >= kNumPredefinedCids) {
      ASSERT(Instance::Cast(Object::Handle(raw_obj)).IsValidNativeIndex(0));
      TypedDataPtr native_fields = *reinterpret_cast<TypedDataPtr*>(
          ObjectLayout::ToAddr(raw_obj) + sizeof(ObjectLayout));
      if (native_fields == TypedData::null()) {
        *value = 0;
      } else {
        *value = *bit_cast<intptr_t*, uint8_t*>(native_fields->ptr()->data());
      }
      return true;
    }
  }
  return false;
}

bool Api::GetNativeBooleanArgument(NativeArguments* arguments,
                                   int arg_index,
                                   bool* value) {
  NoSafepointScope no_safepoint_scope;
  ObjectPtr raw_obj = arguments->NativeArgAt(arg_index);
  if (raw_obj->IsHeapObject()) {
    intptr_t cid = raw_obj->GetClassId();
    if (cid == kBoolCid) {
      *value = (raw_obj == Object::bool_true().raw());
      return true;
    }
    if (cid == kNullCid) {
      *value = false;
      return true;
    }
  }
  return false;
}

bool Api::GetNativeIntegerArgument(NativeArguments* arguments,
                                   int arg_index,
                                   int64_t* value) {
  NoSafepointScope no_safepoint_scope;
  ObjectPtr raw_obj = arguments->NativeArgAt(arg_index);
  if (raw_obj->IsHeapObject()) {
    intptr_t cid = raw_obj->GetClassId();
    if (cid == kMintCid) {
      *value = static_cast<MintPtr>(raw_obj)->ptr()->value_;
      return true;
    }
    return false;
  }
  *value = Smi::Value(static_cast<SmiPtr>(raw_obj));
  return true;
}

bool Api::GetNativeDoubleArgument(NativeArguments* arguments,
                                  int arg_index,
                                  double* value) {
  NoSafepointScope no_safepoint_scope;
  ObjectPtr raw_obj = arguments->NativeArgAt(arg_index);
  if (raw_obj->IsHeapObject()) {
    intptr_t cid = raw_obj->GetClassId();
    if (cid == kDoubleCid) {
      *value = static_cast<DoublePtr>(raw_obj)->ptr()->value_;
      return true;
    }
    if (cid == kMintCid) {
      *value =
          static_cast<double>(static_cast<MintPtr>(raw_obj)->ptr()->value_);
      return true;
    }
    return false;
  }
  *value = static_cast<double>(Smi::Value(static_cast<SmiPtr>(raw_obj)));
  return true;
}

bool Api::GetNativeFieldsOfArgument(NativeArguments* arguments,
                                    int arg_index,
                                    int num_fields,
                                    intptr_t* field_values) {
  NoSafepointScope no_safepoint_scope;
  ObjectPtr raw_obj = arguments->NativeArgAt(arg_index);
  if (raw_obj->IsHeapObject()) {
    intptr_t cid = raw_obj->GetClassId();
    if (cid >= kNumPredefinedCids) {
      TypedDataPtr native_fields = *reinterpret_cast<TypedDataPtr*>(
          ObjectLayout::ToAddr(raw_obj) + sizeof(ObjectLayout));
      if (native_fields == TypedData::null()) {
        memset(field_values, 0, (num_fields * sizeof(field_values[0])));
      } else if (num_fields == Smi::Value(native_fields->ptr()->length_)) {
        intptr_t* native_values =
            bit_cast<intptr_t*, uint8_t*>(native_fields->ptr()->data());
        memmove(field_values, native_values,
                (num_fields * sizeof(field_values[0])));
      }
      return true;
    }
  }
  return false;
}

void Api::SetWeakHandleReturnValue(NativeArguments* args,
                                   Dart_WeakPersistentHandle retval) {
  args->SetReturnUnsafe(FinalizablePersistentHandle::Cast(retval)->raw());
}

PersistentHandle* PersistentHandle::Cast(Dart_PersistentHandle handle) {
  ASSERT(IsolateGroup::Current()->api_state()->IsValidPersistentHandle(handle));
  return reinterpret_cast<PersistentHandle*>(handle);
}

FinalizablePersistentHandle* FinalizablePersistentHandle::Cast(
    Dart_WeakPersistentHandle handle) {
#if defined(DEBUG)
  ApiState* state = IsolateGroup::Current()->api_state();
  ASSERT(state->IsValidWeakPersistentHandle(handle));
#endif
  return reinterpret_cast<FinalizablePersistentHandle*>(handle);
}

void FinalizablePersistentHandle::Finalize(
    IsolateGroup* isolate_group,
    FinalizablePersistentHandle* handle) {
  if (!handle->raw()->IsHeapObject()) {
    return;  // Free handle.
  }
  Dart_WeakPersistentHandleFinalizer callback = handle->callback();
  ASSERT(callback != NULL);
  void* peer = handle->peer();
  Dart_WeakPersistentHandle object = handle->apiHandle();
  (*callback)(isolate_group->embedder_data(), object, peer);
  ApiState* state = isolate_group->api_state();
  ASSERT(state != NULL);
  state->FreeWeakPersistentHandle(handle);
}

// --- Handles ---

DART_EXPORT bool Dart_IsError(Dart_Handle handle) {
  Thread* thread = Thread::Current();
  TransitionNativeToVM transition(thread);
  return Api::IsError(handle);
}

DART_EXPORT void Dart_KillIsolate(Dart_Isolate handle) {
  Isolate* isolate = reinterpret_cast<Isolate*>(handle);
  CHECK_ISOLATE(isolate);
  Isolate::KillIfExists(isolate, Isolate::kKillMsg);
}

DART_EXPORT bool Dart_IsApiError(Dart_Handle object) {
  Thread* thread = Thread::Current();
  TransitionNativeToVM transition(thread);
  return Api::ClassId(object) == kApiErrorCid;
}

DART_EXPORT bool Dart_IsUnhandledExceptionError(Dart_Handle object) {
  Thread* thread = Thread::Current();
  TransitionNativeToVM transition(thread);
  return Api::ClassId(object) == kUnhandledExceptionCid;
}

DART_EXPORT bool Dart_IsCompilationError(Dart_Handle object) {
  if (::Dart_IsUnhandledExceptionError(object)) {
    DARTSCOPE(Thread::Current());
    const UnhandledException& error =
        UnhandledException::Cast(Object::Handle(Z, Api::UnwrapHandle(object)));
    const Instance& exc = Instance::Handle(Z, error.exception());
    return IsCompiletimeErrorObject(Z, exc);
  }

  Thread* thread = Thread::Current();
  TransitionNativeToVM transition(thread);
  return Api::ClassId(object) == kLanguageErrorCid;
}

DART_EXPORT bool Dart_IsFatalError(Dart_Handle object) {
  Thread* thread = Thread::Current();
  TransitionNativeToVM transition(thread);
  return Api::ClassId(object) == kUnwindErrorCid;
}

DART_EXPORT const char* Dart_GetError(Dart_Handle handle) {
  DARTSCOPE(Thread::Current());
  API_TIMELINE_DURATION(T);
  const Object& obj = Object::Handle(Z, Api::UnwrapHandle(handle));
  return GetErrorString(T, obj);
}

DART_EXPORT bool Dart_ErrorHasException(Dart_Handle handle) {
  DARTSCOPE(Thread::Current());
  const Object& obj = Object::Handle(Z, Api::UnwrapHandle(handle));
  return obj.IsUnhandledException();
}

DART_EXPORT Dart_Handle Dart_ErrorGetException(Dart_Handle handle) {
  DARTSCOPE(Thread::Current());
  const Object& obj = Object::Handle(Z, Api::UnwrapHandle(handle));
  if (obj.IsUnhandledException()) {
    const UnhandledException& error = UnhandledException::Cast(obj);
    return Api::NewHandle(T, error.exception());
  } else if (obj.IsError()) {
    return Api::NewError("This error is not an unhandled exception error.");
  } else {
    return Api::NewError("Can only get exceptions from error handles.");
  }
}

DART_EXPORT Dart_Handle Dart_ErrorGetStackTrace(Dart_Handle handle) {
  DARTSCOPE(Thread::Current());
  const Object& obj = Object::Handle(Z, Api::UnwrapHandle(handle));
  if (obj.IsUnhandledException()) {
    const UnhandledException& error = UnhandledException::Cast(obj);
    return Api::NewHandle(T, error.stacktrace());
  } else if (obj.IsError()) {
    return Api::NewError("This error is not an unhandled exception error.");
  } else {
    return Api::NewError("Can only get stacktraces from error handles.");
  }
}

DART_EXPORT Dart_Handle Dart_NewApiError(const char* error) {
  DARTSCOPE(Thread::Current());
  CHECK_CALLBACK_STATE(T);

  const String& message = String::Handle(Z, String::New(error));
  return Api::NewHandle(T, ApiError::New(message));
}

DART_EXPORT Dart_Handle Dart_NewCompilationError(const char* error) {
  DARTSCOPE(Thread::Current());
  CHECK_CALLBACK_STATE(T);

  const String& message = String::Handle(Z, String::New(error));
  return Api::NewHandle(T, LanguageError::New(message));
}

DART_EXPORT Dart_Handle Dart_NewUnhandledExceptionError(Dart_Handle exception) {
  DARTSCOPE(Thread::Current());
  CHECK_CALLBACK_STATE(T);

  Instance& obj = Instance::Handle(Z);
  intptr_t class_id = Api::ClassId(exception);
  if ((class_id == kApiErrorCid) || (class_id == kLanguageErrorCid)) {
    const Object& excp = Object::Handle(Z, Api::UnwrapHandle(exception));
    obj = String::New(GetErrorString(T, excp));
  } else {
    obj = Api::UnwrapInstanceHandle(Z, exception).raw();
    if (obj.IsNull()) {
      RETURN_TYPE_ERROR(Z, exception, Instance);
    }
  }
  const StackTrace& stacktrace = StackTrace::Handle(Z);
  return Api::NewHandle(T, UnhandledException::New(obj, stacktrace));
}

DART_EXPORT void Dart_PropagateError(Dart_Handle handle) {
  Thread* thread = Thread::Current();
  CHECK_ISOLATE(thread->isolate());
  TransitionNativeToVM transition(thread);
  const Object& obj = Object::Handle(thread->zone(), Api::UnwrapHandle(handle));
  if (!obj.IsError()) {
    FATAL1(
        "%s expects argument 'handle' to be an error handle.  "
        "Did you forget to check Dart_IsError first?",
        CURRENT_FUNC);
  }
  if (thread->top_exit_frame_info() == 0) {
    // There are no dart frames on the stack so it would be illegal to
    // propagate an error here.
    FATAL("No Dart frames on stack, cannot propagate error.");
  }
  // Unwind all the API scopes till the exit frame before propagating.
  const Error* error;
  {
    // We need to preserve the error object across the destruction of zones
    // when the ApiScopes are unwound.  By using NoSafepointScope, we can ensure
    // that GC won't touch the raw error object before creating a valid
    // handle for it in the surviving zone.
    NoSafepointScope no_safepoint;
    ErrorPtr raw_error = Api::UnwrapErrorHandle(thread->zone(), handle).raw();
    thread->UnwindScopes(thread->top_exit_frame_info());
    // Note that thread's zone is different here than at the beginning of this
    // function.
    error = &Error::Handle(thread->zone(), raw_error);
  }
  Exceptions::PropagateError(*error);
  UNREACHABLE();
}

DART_EXPORT Dart_Handle Dart_ToString(Dart_Handle object) {
  DARTSCOPE(Thread::Current());
  const Object& obj = Object::Handle(Z, Api::UnwrapHandle(object));
  if (obj.IsString()) {
    return Api::NewHandle(T, obj.raw());
  } else if (obj.IsInstance()) {
    CHECK_CALLBACK_STATE(T);
    const Instance& receiver = Instance::Cast(obj);
    return Api::NewHandle(T, DartLibraryCalls::ToString(receiver));
  } else {
    CHECK_CALLBACK_STATE(T);
    // This is a VM internal object. Call the C++ method of printing.
    return Api::NewHandle(T, String::New(obj.ToCString()));
  }
}

DART_EXPORT bool Dart_IdentityEquals(Dart_Handle obj1, Dart_Handle obj2) {
  DARTSCOPE(Thread::Current());
  {
    NoSafepointScope no_safepoint_scope;
    if (Api::UnwrapHandle(obj1) == Api::UnwrapHandle(obj2)) {
      return true;
    }
  }
  const Object& object1 = Object::Handle(Z, Api::UnwrapHandle(obj1));
  const Object& object2 = Object::Handle(Z, Api::UnwrapHandle(obj2));
  if (object1.IsInstance() && object2.IsInstance()) {
    return Instance::Cast(object1).IsIdenticalTo(Instance::Cast(object2));
  }
  return false;
}

DART_EXPORT Dart_Handle
Dart_HandleFromPersistent(Dart_PersistentHandle object) {
  Thread* thread = Thread::Current();
  Isolate* isolate = thread->isolate();
  CHECK_ISOLATE(isolate);
  ApiState* state = isolate->group()->api_state();
  ASSERT(state != NULL);
  TransitionNativeToVM transition(thread);
  NoSafepointScope no_safepoint_scope;
  PersistentHandle* ref = PersistentHandle::Cast(object);
  return Api::NewHandle(thread, ref->raw());
}

DART_EXPORT Dart_Handle
Dart_HandleFromWeakPersistent(Dart_WeakPersistentHandle object) {
  Thread* thread = Thread::Current();
  Isolate* isolate = thread->isolate();
  CHECK_ISOLATE(isolate);
  ApiState* state = isolate->group()->api_state();
  ASSERT(state != NULL);
  TransitionNativeToVM transition(thread);
  NoSafepointScope no_safepoint_scope;
  FinalizablePersistentHandle* weak_ref =
      FinalizablePersistentHandle::Cast(object);
  return Api::NewHandle(thread, weak_ref->raw());
}

DART_EXPORT Dart_PersistentHandle Dart_NewPersistentHandle(Dart_Handle object) {
  DARTSCOPE(Thread::Current());
  Isolate* I = T->isolate();
  ApiState* state = I->group()->api_state();
  ASSERT(state != NULL);
  const Object& old_ref = Object::Handle(Z, Api::UnwrapHandle(object));
  PersistentHandle* new_ref = state->AllocatePersistentHandle();
  new_ref->set_raw(old_ref);
  return new_ref->apiHandle();
}

DART_EXPORT void Dart_SetPersistentHandle(Dart_PersistentHandle obj1,
                                          Dart_Handle obj2) {
  DARTSCOPE(Thread::Current());
  Isolate* I = T->isolate();
  ApiState* state = I->group()->api_state();
  ASSERT(state != NULL);
  ASSERT(state->IsValidPersistentHandle(obj1));
  const Object& obj2_ref = Object::Handle(Z, Api::UnwrapHandle(obj2));
  PersistentHandle* obj1_ref = PersistentHandle::Cast(obj1);
  obj1_ref->set_raw(obj2_ref);
}

static Dart_WeakPersistentHandle AllocateFinalizableHandle(
    Thread* thread,
    const Object& ref,
    void* peer,
    intptr_t external_allocation_size,
    Dart_WeakPersistentHandleFinalizer callback) {
  if (!ref.raw()->IsHeapObject()) {
    return NULL;
  }
  FinalizablePersistentHandle* finalizable_ref =
      FinalizablePersistentHandle::New(thread->isolate(), ref, peer, callback,
                                       external_allocation_size);
  return finalizable_ref->apiHandle();
}

static Dart_WeakPersistentHandle AllocateFinalizableHandle(
    Thread* thread,
    Dart_Handle object,
    void* peer,
    intptr_t external_allocation_size,
    Dart_WeakPersistentHandleFinalizer callback) {
  REUSABLE_OBJECT_HANDLESCOPE(thread);
  Object& ref = thread->ObjectHandle();
  ref = Api::UnwrapHandle(object);
  return AllocateFinalizableHandle(thread, ref, peer, external_allocation_size,
                                   callback);
}

DART_EXPORT Dart_WeakPersistentHandle
Dart_NewWeakPersistentHandle(Dart_Handle object,
                             void* peer,
                             intptr_t external_allocation_size,
                             Dart_WeakPersistentHandleFinalizer callback) {
  Thread* thread = Thread::Current();
  CHECK_ISOLATE(thread->isolate());
  if (callback == NULL) {
    return NULL;
  }
  TransitionNativeToVM transition(thread);
  return AllocateFinalizableHandle(thread, object, peer,
                                   external_allocation_size, callback);
}

DART_EXPORT void Dart_DeletePersistentHandle(Dart_PersistentHandle object) {
  IsolateGroup* isolate_group = IsolateGroup::Current();
  CHECK_ISOLATE_GROUP(isolate_group);
  NoSafepointScope no_safepoint_scope;
  ApiState* state = isolate_group->api_state();
  ASSERT(state != NULL);
  ASSERT(state->IsActivePersistentHandle(object));
  PersistentHandle* ref = PersistentHandle::Cast(object);
  ASSERT(!state->IsProtectedHandle(ref));
  if (!state->IsProtectedHandle(ref)) {
    state->FreePersistentHandle(ref);
  }
}

DART_EXPORT void Dart_DeleteWeakPersistentHandle(
    Dart_WeakPersistentHandle object) {
  IsolateGroup* isolate_group = IsolateGroup::Current();
  CHECK_ISOLATE_GROUP(isolate_group);
  NoSafepointScope no_safepoint_scope;
  ApiState* state = isolate_group->api_state();
  ASSERT(state != NULL);
  ASSERT(state->IsActiveWeakPersistentHandle(object));
  auto weak_ref = FinalizablePersistentHandle::Cast(object);
  weak_ref->EnsureFreeExternal(isolate_group);
  state->FreeWeakPersistentHandle(weak_ref);
}

// --- Initialization and Globals ---

DART_EXPORT const char* Dart_VersionString() {
  return Version::String();
}

DART_EXPORT char* Dart_Initialize(Dart_InitializeParams* params) {
  if (params == NULL) {
    return strdup(
        "Dart_Initialize: "
        "Dart_InitializeParams is null.");
  }

  if (params->version != DART_INITIALIZE_PARAMS_CURRENT_VERSION) {
    return strdup(
        "Dart_Initialize: "
        "Invalid Dart_InitializeParams version.");
  }

  return Dart::Init(params->vm_snapshot_data, params->vm_snapshot_instructions,
                    params->create_group, params->initialize_isolate,
                    params->shutdown_isolate, params->cleanup_isolate,
                    params->cleanup_group, params->thread_exit,
                    params->file_open, params->file_read, params->file_write,
                    params->file_close, params->entropy_source,
                    params->get_service_assets, params->start_kernel_isolate,
                    params->code_observer);
}

DART_EXPORT char* Dart_Cleanup() {
  CHECK_NO_ISOLATE(Isolate::Current());
  return Dart::Cleanup();
}

DART_EXPORT char* Dart_SetVMFlags(int argc, const char** argv) {
  return Flags::ProcessCommandLineFlags(argc, argv);
}

DART_EXPORT bool Dart_IsVMFlagSet(const char* flag_name) {
  return Flags::IsSet(flag_name);
}

#if !defined(PRODUCT)
#define VM_METRIC_API(type, variable, name, unit)                              \
  DART_EXPORT int64_t Dart_VM##variable##Metric() {                            \
    return vm_metric_##variable.Value();                                       \
  }
VM_METRIC_LIST(VM_METRIC_API);
#undef VM_METRIC_API
#else  // !defined(PRODUCT)
#define VM_METRIC_API(type, variable, name, unit)                              \
  DART_EXPORT int64_t Dart_VM##variable##Metric() { return -1; }
VM_METRIC_LIST(VM_METRIC_API)
#undef VM_METRIC_API
#endif  // !defined(PRODUCT)

#define ISOLATE_GROUP_METRIC_API(type, variable, name, unit)                   \
  DART_EXPORT int64_t Dart_Isolate##variable##Metric(Dart_Isolate isolate) {   \
    if (isolate == nullptr) {                                                  \
      FATAL1("%s expects argument 'isolate' to be non-null.", CURRENT_FUNC);   \
    }                                                                          \
    Isolate* iso = reinterpret_cast<Isolate*>(isolate);                        \
    return iso->group()->Get##variable##Metric()->Value();                     \
  }
ISOLATE_GROUP_METRIC_LIST(ISOLATE_GROUP_METRIC_API)
#undef ISOLATE_GROUP_METRIC_API

#if !defined(PRODUCT)
#define ISOLATE_METRIC_API(type, variable, name, unit)                         \
  DART_EXPORT int64_t Dart_Isolate##variable##Metric(Dart_Isolate isolate) {   \
    if (isolate == NULL) {                                                     \
      FATAL1("%s expects argument 'isolate' to be non-null.", CURRENT_FUNC);   \
    }                                                                          \
    Isolate* iso = reinterpret_cast<Isolate*>(isolate);                        \
    return iso->Get##variable##Metric()->Value();                              \
  }
ISOLATE_METRIC_LIST(ISOLATE_METRIC_API)
#undef ISOLATE_METRIC_API
#else  // !defined(PRODUCT)
#define ISOLATE_METRIC_API(type, variable, name, unit)                         \
  DART_EXPORT int64_t Dart_Isolate##variable##Metric(Dart_Isolate isolate) {   \
    return -1;                                                                 \
  }
ISOLATE_METRIC_LIST(ISOLATE_METRIC_API)
#undef ISOLATE_METRIC_API
#endif  // !defined(PRODUCT)

// --- Isolates ---

static Dart_Isolate CreateIsolate(IsolateGroup* group,
                                  bool is_new_group,
                                  const char* name,
                                  void* isolate_data,
                                  char** error) {
  CHECK_NO_ISOLATE(Isolate::Current());

  auto source = group->source();
  Isolate* I = Dart::CreateIsolate(name, source->flags, group);
  if (I == NULL) {
    if (error != NULL) {
      *error = strdup("Isolate creation failed");
    }
    return reinterpret_cast<Dart_Isolate>(NULL);
  }

  Thread* T = Thread::Current();
  bool success = false;
  {
    StackZone zone(T);
    HANDLESCOPE(T);
    // We enter an API scope here as InitializeIsolate could compile some
    // bootstrap library files which call out to a tag handler that may create
    // Api Handles when an error is encountered.
    T->EnterApiScope();
    const Error& error_obj = Error::Handle(
        Z, Dart::InitializeIsolate(
               source->snapshot_data, source->snapshot_instructions,
               source->kernel_buffer, source->kernel_buffer_size,
               is_new_group ? nullptr : group, isolate_data));
    if (error_obj.IsNull()) {
#if defined(DEBUG) && !defined(DART_PRECOMPILED_RUNTIME)
      if (FLAG_check_function_fingerprints && source->kernel_buffer == NULL) {
        Library::CheckFunctionFingerprints();
      }
#endif  // defined(DEBUG) && !defined(DART_PRECOMPILED_RUNTIME).
      success = true;
    } else if (error != NULL) {
      *error = strdup(error_obj.ToErrorCString());
    }
    // We exit the API scope entered above.
    T->ExitApiScope();
  }

  if (success) {
    if (is_new_group) {
      I->heap()->InitGrowthControl();
    }
    // A Thread structure has been associated to the thread, we do the
    // safepoint transition explicitly here instead of using the
    // TransitionXXX scope objects as the reverse transition happens
    // outside this scope in Dart_ShutdownIsolate/Dart_ExitIsolate.
    T->set_execution_state(Thread::kThreadInNative);
    T->EnterSafepoint();
    if (error != NULL) {
      *error = NULL;
    }
    return Api::CastIsolate(I);
  }

  Dart::ShutdownIsolate();
  return reinterpret_cast<Dart_Isolate>(NULL);
}

static bool IsServiceOrKernelIsolateName(const char* name) {
  if (ServiceIsolate::NameEquals(name)) {
    ASSERT(!ServiceIsolate::Exists());
    return true;
  }
#if !defined(DART_PRECOMPILED_RUNTIME)
  if (KernelIsolate::NameEquals(name)) {
    ASSERT(!KernelIsolate::Exists());
    return true;
  }
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
  return false;
}

Isolate* CreateWithinExistingIsolateGroupAOT(IsolateGroup* group,
                                             const char* name,
                                             char** error) {
#if defined(DART_PRECOMPILED_RUNTIME)
  API_TIMELINE_DURATION(Thread::Current());
  CHECK_NO_ISOLATE(Isolate::Current());

  auto spawning_group = group;

  Isolate* isolate = reinterpret_cast<Isolate*>(
      CreateIsolate(spawning_group, /*is_new_group=*/false, name,
                    /*isolate_data=*/nullptr, error));
  if (isolate == nullptr) return nullptr;

  auto source = spawning_group->source();
  ASSERT(isolate->source() == source);

  return isolate;
#else
  UNREACHABLE();
#endif
}

Isolate* CreateWithinExistingIsolateGroup(IsolateGroup* group,
                                          const char* name,
                                          char** error) {
#if !defined(DART_PRECOMPILED_RUNTIME)
  API_TIMELINE_DURATION(Thread::Current());
  CHECK_NO_ISOLATE(Isolate::Current());

  // During isolate start we'll make a temporary anonymous group from the same
  // [source]. Once the isolate has been fully loaded we will merge it's heap
  // into the shared heap.
  auto spawning_group = new IsolateGroup(group->shareable_source(),
                                         /*isolate_group_data=*/nullptr);
  IsolateGroup::RegisterIsolateGroup(spawning_group);
  spawning_group->CreateHeap(
      /*is_vm_isolate=*/false,
      IsServiceOrKernelIsolateName(group->source()->name));

  Isolate* isolate = reinterpret_cast<Isolate*>(
      CreateIsolate(spawning_group, /*is_new_group=*/false, name,
                    /*isolate_data=*/nullptr, error));
  if (isolate == nullptr) return nullptr;

  auto source = spawning_group->source();
  ASSERT(isolate->source() == source);

  if (source->script_kernel_buffer != nullptr) {
    Dart_EnterScope();
    {
      Thread* T = Thread::Current();
      TransitionNativeToVM transition(T);
      HANDLESCOPE(T);
      StackZone zone(T);

      // NOTE: We do not attach a finalizer for this object, because the
      // embedder will free it once the isolate group has shutdown.
      const auto& td = ExternalTypedData::Handle(ExternalTypedData::New(
          kExternalTypedDataUint8ArrayCid,
          const_cast<uint8_t*>(source->script_kernel_buffer),
          source->script_kernel_size, Heap::kOld));

      std::unique_ptr<kernel::Program> program =
          kernel::Program::ReadFromTypedData(td,
                                             const_cast<const char**>(error));
      if (program == nullptr) {
        UNIMPLEMENTED();
      }
      const Object& tmp =
          kernel::KernelLoader::LoadEntireProgram(program.get());

      // If the existing isolate could spawn with a root library we should be
      // able to do the same
      RELEASE_ASSERT(!tmp.IsNull() && tmp.IsLibrary());
      isolate->object_store()->set_root_library(Library::Cast(tmp));
    }
    Dart_ExitScope();
  }

  // If we are running in AppJIT training mode we'll have to remap class ids.
  if (auto permutation_map = group->source()->cid_permutation_map.get()) {
    Dart_EnterScope();
    {
      auto T = Thread::Current();
      TransitionNativeToVM transition(T);
      HANDLESCOPE(T);

      // Remap all class ids loaded atm (e.g. from snapshot) and do appropriate
      // re-hashing of constants and types.
      ClassFinalizer::RemapClassIds(permutation_map);
      // Types use cid's as part of their hashes.
      ClassFinalizer::RehashTypes();
      // Const objects use cid's as part of their hashes.
      isolate->RehashConstants();
    }
    Dart_ExitScope();
  }

  auto thread = Thread::Current();
  {
    TransitionNativeToVM native_to_vm(thread);

    // Ensure new space is empty and there are no threads running.
    BackgroundCompiler::Stop(isolate);
    isolate->heap()->new_space()->Evacuate();
    isolate->heap()->WaitForMarkerTasks(thread);
    isolate->heap()->WaitForSweeperTasks(thread);
    RELEASE_ASSERT(isolate->heap()->new_space()->UsedInWords() == 0);
    RELEASE_ASSERT(isolate->heap()->old_space()->tasks() == 0);
  }

  Dart_ExitIsolate();
  {
    const bool kBypassSafepoint = false;
    Thread::EnterIsolateGroupAsHelper(group, Thread::kUnknownTask,
                                      kBypassSafepoint);
    ASSERT(group == IsolateGroup::Current());

    {
      auto thread = Thread::Current();

      // Prevent additions of new isolates to [group] until we're done.
      group->RunWithLockedGroup([&]() {
        // Ensure no other old space GC tasks are running and "occupy" the old
        // space.
        {
          auto old_space = group->heap()->old_space();
          MonitorLocker ml(old_space->tasks_lock());
          while (old_space->tasks() > 0) {
            ml.WaitWithSafepointCheck(thread);
          }
          old_space->set_tasks(1);
        }

        // Merge the heap from [spawning_group] to [group].
        {
          SafepointOperationScope safepoint_scope(thread);
          group->heap()->MergeOtherHeap(isolate->group()->heap());
        }

        spawning_group->UnregisterIsolate(isolate);
        const bool shutdown_group =
            spawning_group->UnregisterIsolateDecrementCount(isolate);
        ASSERT(shutdown_group);

        isolate->isolate_group_ = group;
        group->RegisterIsolateLocked(isolate);
        isolate->class_table()->shared_class_table_ =
            group->shared_class_table();
        isolate->set_shared_class_table(group->shared_class_table());

        // Even though the mutator thread was descheduled, it will still
        // retain its [Thread] structure with valid isolate/isolate_group
        // pointers.
        // If GC happens before the mutator gets scheduled again, we have to
        // ensure the isolate group change is reflected in the threads
        // structure.
        ASSERT(isolate->mutator_thread() != nullptr);
        ASSERT(isolate->mutator_thread()->isolate_group() == spawning_group);
        isolate->mutator_thread()->isolate_group_ = group;

        // Allow other old space GC tasks to run again.
        {
          auto old_space = group->heap()->old_space();
          MonitorLocker ml(old_space->tasks_lock());
          ASSERT(old_space->tasks() == 1);
          old_space->set_tasks(0);
          ml.NotifyAll();
        }
      });
    }

    Thread::ExitIsolateGroupAsHelper(kBypassSafepoint);
  }

  spawning_group->Shutdown();

  Dart_EnterIsolate(Api::CastIsolate(isolate));
  ASSERT(Thread::Current()->isolate_group() == isolate->group());

  return isolate;
#else
  UNREACHABLE();
#endif
}

DART_EXPORT void Dart_IsolateFlagsInitialize(Dart_IsolateFlags* flags) {
  Isolate::FlagsInitialize(flags);
}

DART_EXPORT Dart_Isolate
Dart_CreateIsolateGroup(const char* script_uri,
                        const char* name,
                        const uint8_t* snapshot_data,
                        const uint8_t* snapshot_instructions,
                        Dart_IsolateFlags* flags,
                        void* isolate_group_data,
                        void* isolate_data,
                        char** error) {
  API_TIMELINE_DURATION(Thread::Current());

  Dart_IsolateFlags api_flags;
  if (flags == nullptr) {
    Isolate::FlagsInitialize(&api_flags);
    flags = &api_flags;
  }

  const char* non_null_name = name == nullptr ? "isolate" : name;
  std::unique_ptr<IsolateGroupSource> source(
      new IsolateGroupSource(script_uri, non_null_name, snapshot_data,
                             snapshot_instructions, nullptr, -1, *flags));
  auto group = new IsolateGroup(std::move(source), isolate_group_data);
  group->CreateHeap(
      /*is_vm_isolate=*/false, IsServiceOrKernelIsolateName(non_null_name));
  IsolateGroup::RegisterIsolateGroup(group);
  Dart_Isolate isolate = CreateIsolate(group, /*is_new_group=*/true,
                                       non_null_name, isolate_data, error);
  if (isolate != nullptr) {
    group->set_initial_spawn_successful();
  }
  return isolate;
}

DART_EXPORT Dart_Isolate
Dart_CreateIsolateGroupFromKernel(const char* script_uri,
                                  const char* name,
                                  const uint8_t* kernel_buffer,
                                  intptr_t kernel_buffer_size,
                                  Dart_IsolateFlags* flags,
                                  void* isolate_group_data,
                                  void* isolate_data,
                                  char** error) {
  API_TIMELINE_DURATION(Thread::Current());

  Dart_IsolateFlags api_flags;
  if (flags == nullptr) {
    Isolate::FlagsInitialize(&api_flags);
    flags = &api_flags;
  }

  const char* non_null_name = name == nullptr ? "isolate" : name;
  std::shared_ptr<IsolateGroupSource> source(
      new IsolateGroupSource(script_uri, non_null_name, nullptr, nullptr,
                             kernel_buffer, kernel_buffer_size, *flags));
  auto group = new IsolateGroup(source, isolate_group_data);
  IsolateGroup::RegisterIsolateGroup(group);
  group->CreateHeap(
      /*is_vm_isolate=*/false, IsServiceOrKernelIsolateName(non_null_name));
  Dart_Isolate isolate = CreateIsolate(group, /*is_new_group=*/true,
                                       non_null_name, isolate_data, error);
  if (isolate != nullptr) {
    group->set_initial_spawn_successful();
  }
  return isolate;
}

DART_EXPORT void Dart_ShutdownIsolate() {
  Thread* T = Thread::Current();
  Isolate* I = T->isolate();
  CHECK_ISOLATE(I);

  // The Thread structure is disassociated from the isolate, we do the
  // safepoint transition explicitly here instead of using the TransitionXXX
  // scope objects as the original transition happened outside this scope in
  // Dart_EnterIsolate/Dart_CreateIsolateGroup.
  ASSERT(T->execution_state() == Thread::kThreadInNative);
  T->ExitSafepoint();
  T->set_execution_state(Thread::kThreadInVM);

  I->WaitForOutstandingSpawns();

  // Release any remaining API scopes.
  ApiLocalScope* scope = T->api_top_scope();
  while (scope != NULL) {
    ApiLocalScope* previous = scope->previous();
    delete scope;
    scope = previous;
  }
  T->set_api_top_scope(NULL);

  {
    StackZone zone(T);
    HandleScope handle_scope(T);
    Dart::RunShutdownCallback();
  }
  Dart::ShutdownIsolate();
}

DART_EXPORT Dart_Isolate Dart_CurrentIsolate() {
  return Api::CastIsolate(Isolate::Current());
}

DART_EXPORT void* Dart_CurrentIsolateData() {
  Isolate* isolate = Isolate::Current();
  CHECK_ISOLATE(isolate);
  NoSafepointScope no_safepoint_scope;
  return isolate->init_callback_data();
}

DART_EXPORT void* Dart_IsolateData(Dart_Isolate isolate) {
  if (isolate == NULL) {
    FATAL1("%s expects argument 'isolate' to be non-null.", CURRENT_FUNC);
  }
  // TODO(http://dartbug.com/16615): Validate isolate parameter.
  return reinterpret_cast<Isolate*>(isolate)->init_callback_data();
}

DART_EXPORT Dart_IsolateGroup Dart_CurrentIsolateGroup() {
  return Api::CastIsolateGroup(IsolateGroup::Current());
}

DART_EXPORT void* Dart_CurrentIsolateGroupData() {
  IsolateGroup* isolate_group = IsolateGroup::Current();
  CHECK_ISOLATE_GROUP(isolate_group);
  NoSafepointScope no_safepoint_scope;
  return isolate_group->embedder_data();
}

DART_EXPORT void* Dart_IsolateGroupData(Dart_Isolate isolate) {
  if (isolate == NULL) {
    FATAL1("%s expects argument 'isolate' to be non-null.", CURRENT_FUNC);
  }
  // TODO(http://dartbug.com/16615): Validate isolate parameter.
  return reinterpret_cast<Isolate*>(isolate)->group()->embedder_data();
}

DART_EXPORT Dart_Handle Dart_DebugName() {
  DARTSCOPE(Thread::Current());
  Isolate* I = T->isolate();
  return Api::NewHandle(
      T, String::NewFormatted("(%" Pd64 ") '%s'",
                              static_cast<int64_t>(I->main_port()), I->name()));
}

DART_EXPORT const char* Dart_IsolateServiceId(Dart_Isolate isolate) {
  if (isolate == NULL) {
    FATAL1("%s expects argument 'isolate' to be non-null.", CURRENT_FUNC);
  }
  // TODO(http://dartbug.com/16615): Validate isolate parameter.
  Isolate* I = reinterpret_cast<Isolate*>(isolate);
  int64_t main_port = static_cast<int64_t>(I->main_port());
  return OS::SCreate(NULL, "isolates/%" Pd64, main_port);
}

DART_EXPORT void Dart_EnterIsolate(Dart_Isolate isolate) {
  CHECK_NO_ISOLATE(Isolate::Current());
  // TODO(http://dartbug.com/16615): Validate isolate parameter.
  Isolate* iso = reinterpret_cast<Isolate*>(isolate);
  if (!Thread::EnterIsolate(iso)) {
    FATAL(
        "Unable to Enter Isolate : "
        "Multiple mutators entering an isolate / "
        "Dart VM is shutting down");
  }
  // A Thread structure has been associated to the thread, we do the
  // safepoint transition explicitly here instead of using the
  // TransitionXXX scope objects as the reverse transition happens
  // outside this scope in Dart_ExitIsolate/Dart_ShutdownIsolate.
  Thread* T = Thread::Current();
  T->set_execution_state(Thread::kThreadInNative);
  T->EnterSafepoint();
}

DART_EXPORT void Dart_StartProfiling() {
#if !defined(PRODUCT)
  if (!FLAG_profiler) {
    FLAG_profiler = true;
    Profiler::Init();
  }
#endif  // !defined(PRODUCT)
}

DART_EXPORT void Dart_StopProfiling() {
#if !defined(PRODUCT)
  if (FLAG_profiler) {
    Profiler::Cleanup();
    FLAG_profiler = false;
  }
#endif  // !defined(PRODUCT)
}

DART_EXPORT void Dart_ThreadDisableProfiling() {
  OSThread* os_thread = OSThread::Current();
  if (os_thread == NULL) {
    return;
  }
  os_thread->DisableThreadInterrupts();
}

DART_EXPORT void Dart_ThreadEnableProfiling() {
  OSThread* os_thread = OSThread::Current();
  if (os_thread == NULL) {
    return;
  }
  os_thread->EnableThreadInterrupts();
}

DART_EXPORT void Dart_AddSymbols(const char* dso_name,
                                 void* buffer,
                                 intptr_t buffer_size) {
  NativeSymbolResolver::AddSymbols(dso_name, buffer, buffer_size);
}

DART_EXPORT bool Dart_WriteProfileToTimeline(Dart_Port main_port,
                                             char** error) {
#if defined(PRODUCT)
  return false;
#else
  if (!FLAG_profiler) {
    if (error != NULL) {
      *error = strdup("The profiler is not running.");
    }
    return false;
  }

  const intptr_t kBufferLength = 512;
  char method[kBufferLength];

  // clang-format off
  intptr_t method_length = snprintf(method, kBufferLength, "{"
      "\"jsonrpc\": \"2.0\","
      "\"method\": \"_writeCpuProfileTimeline\","
      "\"id\": \"\","
      "\"params\": {"
      "  \"isolateId\": \"isolates/%" Pd64 "\","
      "  \"tags\": \"None\""
      "}"
  "}", main_port);
  // clang-format on
  ASSERT(method_length <= kBufferLength);

  char* response = NULL;
  intptr_t response_length;
  bool success = Dart_InvokeVMServiceMethod(
      reinterpret_cast<uint8_t*>(method), method_length,
      reinterpret_cast<uint8_t**>(&response), &response_length, error);
  free(response);
  return success;
#endif
}

DART_EXPORT bool Dart_ShouldPauseOnStart() {
#if defined(PRODUCT)
  return false;
#else
  Isolate* isolate = Isolate::Current();
  CHECK_ISOLATE(isolate);
  NoSafepointScope no_safepoint_scope;
  return isolate->message_handler()->should_pause_on_start();
#endif
}

DART_EXPORT void Dart_SetShouldPauseOnStart(bool should_pause) {
#if defined(PRODUCT)
  if (should_pause) {
    FATAL1("%s(true) is not supported in a PRODUCT build", CURRENT_FUNC);
  }
#else
  Isolate* isolate = Isolate::Current();
  CHECK_ISOLATE(isolate);
  NoSafepointScope no_safepoint_scope;
  if (isolate->is_runnable()) {
    FATAL1("%s expects the current isolate to not be runnable yet.",
           CURRENT_FUNC);
  }
  isolate->message_handler()->set_should_pause_on_start(should_pause);
#endif
}

DART_EXPORT bool Dart_IsPausedOnStart() {
#if defined(PRODUCT)
  return false;
#else
  Isolate* isolate = Isolate::Current();
  CHECK_ISOLATE(isolate);
  NoSafepointScope no_safepoint_scope;
  return isolate->message_handler()->is_paused_on_start();
#endif
}

DART_EXPORT void Dart_SetPausedOnStart(bool paused) {
#if defined(PRODUCT)
  if (paused) {
    FATAL1("%s(true) is not supported in a PRODUCT build", CURRENT_FUNC);
  }
#else
  Isolate* isolate = Isolate::Current();
  CHECK_ISOLATE(isolate);
  NoSafepointScope no_safepoint_scope;
  if (isolate->message_handler()->is_paused_on_start() != paused) {
    isolate->message_handler()->PausedOnStart(paused);
  }
#endif
}

DART_EXPORT bool Dart_ShouldPauseOnExit() {
#if defined(PRODUCT)
  return false;
#else
  Isolate* isolate = Isolate::Current();
  CHECK_ISOLATE(isolate);
  NoSafepointScope no_safepoint_scope;
  return isolate->message_handler()->should_pause_on_exit();
#endif
}

DART_EXPORT void Dart_SetShouldPauseOnExit(bool should_pause) {
#if defined(PRODUCT)
  if (should_pause) {
    FATAL1("%s(true) is not supported in a PRODUCT build", CURRENT_FUNC);
  }
#else
  Isolate* isolate = Isolate::Current();
  CHECK_ISOLATE(isolate);
  NoSafepointScope no_safepoint_scope;
  isolate->message_handler()->set_should_pause_on_exit(should_pause);
#endif
}

DART_EXPORT bool Dart_IsPausedOnExit() {
#if defined(PRODUCT)
  return false;
#else
  Isolate* isolate = Isolate::Current();
  CHECK_ISOLATE(isolate);
  NoSafepointScope no_safepoint_scope;
  return isolate->message_handler()->is_paused_on_exit();
#endif
}

DART_EXPORT void Dart_SetPausedOnExit(bool paused) {
#if defined(PRODUCT)
  if (paused) {
    FATAL1("%s(true) is not supported in a PRODUCT build", CURRENT_FUNC);
  }
#else
  Isolate* isolate = Isolate::Current();
  CHECK_ISOLATE(isolate);
  NoSafepointScope no_safepoint_scope;
  if (isolate->message_handler()->is_paused_on_exit() != paused) {
    isolate->message_handler()->PausedOnExit(paused);
  }
#endif
}

DART_EXPORT void Dart_SetStickyError(Dart_Handle error) {
  Thread* thread = Thread::Current();
  DARTSCOPE(thread);
  Isolate* isolate = thread->isolate();
  CHECK_ISOLATE(isolate);
  NoSafepointScope no_safepoint_scope;
  const Error& error_handle = Api::UnwrapErrorHandle(Z, error);
  if ((isolate->sticky_error() != Error::null()) &&
      (error_handle.raw() != Object::null())) {
    FATAL1("%s expects there to be no sticky error.", CURRENT_FUNC);
  }
  if (!error_handle.IsUnhandledException() &&
      (error_handle.raw() != Object::null())) {
    FATAL1("%s expects the error to be an unhandled exception error or null.",
           CURRENT_FUNC);
  }
  isolate->SetStickyError(error_handle.raw());
}

DART_EXPORT bool Dart_HasStickyError() {
  Thread* T = Thread::Current();
  Isolate* isolate = T->isolate();
  CHECK_ISOLATE(isolate);
  NoSafepointScope no_safepoint_scope;
  return isolate->sticky_error() != Error::null();
}

DART_EXPORT Dart_Handle Dart_GetStickyError() {
  Thread* T = Thread::Current();
  Isolate* I = T->isolate();
  CHECK_ISOLATE(I);
  {
    NoSafepointScope no_safepoint_scope;
    if (I->sticky_error() == Error::null()) {
      return Api::Null();
    }
  }
  TransitionNativeToVM transition(T);
  return Api::NewHandle(T, I->sticky_error());
}

DART_EXPORT void Dart_NotifyIdle(int64_t deadline) {
  Thread* T = Thread::Current();
  CHECK_ISOLATE(T->isolate());
  API_TIMELINE_BEGIN_END(T);
  TransitionNativeToVM transition(T);
  T->isolate()->group()->idle_time_handler()->NotifyIdle(deadline);
}

DART_EXPORT void Dart_NotifyLowMemory() {
  API_TIMELINE_BEGIN_END(Thread::Current());
  Isolate::NotifyLowMemory();
}

DART_EXPORT void Dart_ExitIsolate() {
  Thread* T = Thread::Current();
  CHECK_ISOLATE(T->isolate());
  // The Thread structure is disassociated from the isolate, we do the
  // safepoint transition explicitly here instead of using the TransitionXXX
  // scope objects as the original transition happened outside this scope in
  // Dart_EnterIsolate/Dart_CreateIsolateGroup.
  ASSERT(T->execution_state() == Thread::kThreadInNative);
  T->ExitSafepoint();
  T->set_execution_state(Thread::kThreadInVM);
  Thread::ExitIsolate();
}

#if !defined(DART_PRECOMPILED_RUNTIME)
static uint8_t* ApiReallocate(uint8_t* ptr,
                              intptr_t old_size,
                              intptr_t new_size) {
  return Api::TopScope(Thread::Current())
      ->zone()
      ->Realloc<uint8_t>(ptr, old_size, new_size);
}
#endif

DART_EXPORT Dart_Handle
Dart_CreateSnapshot(uint8_t** vm_snapshot_data_buffer,
                    intptr_t* vm_snapshot_data_size,
                    uint8_t** isolate_snapshot_data_buffer,
                    intptr_t* isolate_snapshot_data_size) {
#if defined(DART_PRECOMPILED_RUNTIME)
  return Api::NewError("Cannot create snapshots on an AOT runtime.");
#else
  DARTSCOPE(Thread::Current());
  API_TIMELINE_DURATION(T);
  Isolate* I = T->isolate();
  if (vm_snapshot_data_buffer != NULL && vm_snapshot_data_size == NULL) {
    RETURN_NULL_ERROR(vm_snapshot_data_size);
  }
  CHECK_NULL(isolate_snapshot_data_buffer);
  CHECK_NULL(isolate_snapshot_data_size);
  // Finalize all classes if needed.
  Dart_Handle state = Api::CheckAndFinalizePendingClasses(T);
  if (Api::IsError(state)) {
    return state;
  }
  BackgroundCompiler::Stop(I);

#if defined(DEBUG)
  I->heap()->CollectAllGarbage();
  {
    HeapIterationScope iteration(T);
    CheckFunctionTypesVisitor check_canonical(T);
    iteration.IterateObjects(&check_canonical);
  }
#endif  // #if defined(DEBUG)

  Symbols::Compact();

  FullSnapshotWriter writer(Snapshot::kFull, vm_snapshot_data_buffer,
                            isolate_snapshot_data_buffer, ApiReallocate,
                            NULL /* vm_image_writer */,
                            NULL /* isolate_image_writer */);
  writer.WriteFullSnapshot();
  if (vm_snapshot_data_buffer != NULL) {
    *vm_snapshot_data_size = writer.VmIsolateSnapshotSize();
  }
  *isolate_snapshot_data_size = writer.IsolateSnapshotSize();
  return Api::Success();
#endif
}

DART_EXPORT bool Dart_IsKernel(const uint8_t* buffer, intptr_t buffer_size) {
  if (buffer_size < 4) {
    return false;
  }
  return (buffer[0] == 0x90) && (buffer[1] == 0xab) && (buffer[2] == 0xcd) &&
         (buffer[3] == 0xef);
}

DART_EXPORT char* Dart_IsolateMakeRunnable(Dart_Isolate isolate) {
  CHECK_NO_ISOLATE(Isolate::Current());
  API_TIMELINE_DURATION(Thread::Current());
  if (isolate == NULL) {
    FATAL1("%s expects argument 'isolate' to be non-null.", CURRENT_FUNC);
  }
  // TODO(16615): Validate isolate parameter.
  Isolate* iso = reinterpret_cast<Isolate*>(isolate);
  const char* error;
  if (iso->object_store()->root_library() == Library::null()) {
    // The embedder should have called Dart_LoadScriptFromKernel by now.
    error = "Missing root library";
  } else {
    error = iso->MakeRunnable();
  }
  if (error != NULL) {
    return strdup(error);
  }
  return NULL;
}

// --- Messages and Ports ---

DART_EXPORT void Dart_SetMessageNotifyCallback(
    Dart_MessageNotifyCallback message_notify_callback) {
  Isolate* isolate = Isolate::Current();
  CHECK_ISOLATE(isolate);

  {
    NoSafepointScope no_safepoint_scope;
    isolate->set_message_notify_callback(message_notify_callback);
  }

  if (message_notify_callback != nullptr && isolate->HasPendingMessages()) {
    ::Dart_ExitIsolate();

    // If a new handler gets installed and there are pending messages in the
    // queue (e.g. OOB messages for doing vm service work) we need to notify
    // the newly registered callback, otherwise the embedder might never get
    // notified about the pending messages.
    message_notify_callback(Api::CastIsolate(isolate));

    ::Dart_EnterIsolate(Api::CastIsolate(isolate));
  }
}

DART_EXPORT Dart_MessageNotifyCallback Dart_GetMessageNotifyCallback() {
  Isolate* isolate = Isolate::Current();
  CHECK_ISOLATE(isolate);
  NoSafepointScope no_safepoint_scope;
  return isolate->message_notify_callback();
}

struct RunLoopData {
  Monitor* monitor;
  bool done;
};

static void RunLoopDone(uword param) {
  RunLoopData* data = reinterpret_cast<RunLoopData*>(param);
  ASSERT(data->monitor != NULL);
  MonitorLocker ml(data->monitor);
  data->done = true;
  ml.Notify();
}

DART_EXPORT Dart_Handle Dart_RunLoop() {
  Isolate* I;
  {
    Thread* T = Thread::Current();
    I = T->isolate();
    CHECK_API_SCOPE(T);
    CHECK_CALLBACK_STATE(T);
  }
  API_TIMELINE_BEGIN_END(Thread::Current());
  // The message handler run loop does not expect to have a current isolate
  // so we exit the isolate here and enter it again after the runloop is done.
  ::Dart_ExitIsolate();
  {
    Monitor monitor;
    MonitorLocker ml(&monitor);
    RunLoopData data;
    data.monitor = &monitor;
    data.done = false;
    I->message_handler()->Run(I->group()->thread_pool(), NULL, RunLoopDone,
                              reinterpret_cast<uword>(&data));
    while (!data.done) {
      ml.Wait();
    }
  }
  ::Dart_EnterIsolate(Api::CastIsolate(I));
  if (I->sticky_error() != Object::null()) {
    Thread* T = Thread::Current();
    TransitionNativeToVM transition(T);
    return Api::NewHandle(T, I->StealStickyError());
  }
  if (FLAG_print_class_table) {
    HANDLESCOPE(Thread::Current());
    I->class_table()->Print();
  }
  return Api::Success();
}

DART_EXPORT Dart_Handle Dart_HandleMessage() {
  Thread* T = Thread::Current();
  Isolate* I = T->isolate();
  CHECK_API_SCOPE(T);
  CHECK_CALLBACK_STATE(T);
  API_TIMELINE_BEGIN_END_BASIC(T);
  TransitionNativeToVM transition(T);
  if (I->message_handler()->HandleNextMessage() != MessageHandler::kOK) {
    return Api::NewHandle(T, T->StealStickyError());
  }
  return Api::Success();
}

DART_EXPORT Dart_Handle Dart_WaitForEvent(int64_t timeout_millis) {
  Thread* T = Thread::Current();
  Isolate* I = T->isolate();
  CHECK_API_SCOPE(T);
  CHECK_CALLBACK_STATE(T);
  API_TIMELINE_BEGIN_END_BASIC(T);
  TransitionNativeToVM transition(T);
  if (I->message_notify_callback() != NULL) {
    return Api::NewError("waitForEventSync is not supported by this embedder");
  }
  Object& result =
      Object::Handle(Z, DartLibraryCalls::EnsureScheduleImmediate());
  if (result.IsError()) {
    return Api::NewHandle(T, result.raw());
  }

  // Drain the microtask queue. Propagate any errors to the entry frame.
  result = DartLibraryCalls::DrainMicrotaskQueue();
  if (result.IsError()) {
    // Persist the error across unwiding scopes before propagating.
    const Error* error;
    {
      NoSafepointScope no_safepoint;
      ErrorPtr raw_error = Error::Cast(result).raw();
      T->UnwindScopes(T->top_exit_frame_info());
      error = &Error::Handle(T->zone(), raw_error);
    }
    Exceptions::PropagateToEntry(*error);
    UNREACHABLE();
    return Api::NewError("Unreachable");
  }

  // Block to wait for messages and then handle them. Propagate any errors to
  // the entry frame.
  if (I->message_handler()->PauseAndHandleAllMessages(timeout_millis) !=
      MessageHandler::kOK) {
    // Persist the error across unwiding scopes before propagating.
    const Error* error;
    {
      NoSafepointScope no_safepoint;
      ErrorPtr raw_error = T->StealStickyError();
      T->UnwindScopes(T->top_exit_frame_info());
      error = &Error::Handle(T->zone(), raw_error);
    }
    Exceptions::PropagateToEntry(*error);
    UNREACHABLE();
    return Api::NewError("Unreachable");
  }
  return Api::Success();
}

DART_EXPORT bool Dart_HandleServiceMessages() {
#if defined(PRODUCT)
  return true;
#else
  Thread* T = Thread::Current();
  Isolate* I = T->isolate();
  CHECK_API_SCOPE(T);
  CHECK_CALLBACK_STATE(T);
  API_TIMELINE_DURATION(T);
  TransitionNativeToVM transition(T);
  ASSERT(I->GetAndClearResumeRequest() == false);
  MessageHandler::MessageStatus status =
      I->message_handler()->HandleOOBMessages();
  bool resume = I->GetAndClearResumeRequest();
  return (status != MessageHandler::kOK) || resume;
#endif
}

DART_EXPORT bool Dart_HasServiceMessages() {
#if defined(PRODUCT)
  return false;
#else
  Isolate* isolate = Isolate::Current();
  ASSERT(isolate);
  NoSafepointScope no_safepoint_scope;
  return isolate->message_handler()->HasOOBMessages();
#endif
}

DART_EXPORT bool Dart_HasLivePorts() {
  Isolate* isolate = Isolate::Current();
  ASSERT(isolate);
  NoSafepointScope no_safepoint_scope;
  return isolate->message_handler()->HasLivePorts();
}

DART_EXPORT bool Dart_Post(Dart_Port port_id, Dart_Handle handle) {
  DARTSCOPE(Thread::Current());
  API_TIMELINE_DURATION(T);
  NoSafepointScope no_safepoint_scope;
  if (port_id == ILLEGAL_PORT) {
    return false;
  }

  // Smis and null can be sent without serialization.
  ObjectPtr raw_obj = Api::UnwrapHandle(handle);
  if (ApiObjectConverter::CanConvert(raw_obj)) {
    return PortMap::PostMessage(
        Message::New(port_id, raw_obj, Message::kNormalPriority));
  }

  const Object& object = Object::Handle(Z, raw_obj);
  MessageWriter writer(false);
  return PortMap::PostMessage(
      writer.WriteMessage(object, port_id, Message::kNormalPriority));
}

DART_EXPORT Dart_Handle Dart_NewSendPort(Dart_Port port_id) {
  DARTSCOPE(Thread::Current());
  CHECK_CALLBACK_STATE(T);
  if (port_id == ILLEGAL_PORT) {
    return Api::NewError("%s: illegal port_id %" Pd64 ".", CURRENT_FUNC,
                         port_id);
  }
  return Api::NewHandle(T, SendPort::New(port_id));
}

DART_EXPORT Dart_Handle Dart_SendPortGetId(Dart_Handle port,
                                           Dart_Port* port_id) {
  DARTSCOPE(Thread::Current());
  CHECK_CALLBACK_STATE(T);
  API_TIMELINE_DURATION(T);
  const SendPort& send_port = Api::UnwrapSendPortHandle(Z, port);
  if (send_port.IsNull()) {
    RETURN_TYPE_ERROR(Z, port, SendPort);
  }
  if (port_id == NULL) {
    RETURN_NULL_ERROR(port_id);
  }
  *port_id = send_port.Id();
  return Api::Success();
}

DART_EXPORT Dart_Port Dart_GetMainPortId() {
  Isolate* isolate = Isolate::Current();
  CHECK_ISOLATE(isolate);
  return isolate->main_port();
}

// --- Scopes ----

DART_EXPORT void Dart_EnterScope() {
  Thread* thread = Thread::Current();
  Isolate* isolate = thread->isolate();
  CHECK_ISOLATE(isolate);
  TransitionNativeToVM transition(thread);
  thread->EnterApiScope();
}

DART_EXPORT void Dart_ExitScope() {
  Thread* thread = Thread::Current();
  CHECK_API_SCOPE(thread);
  TransitionNativeToVM transition(thread);
  thread->ExitApiScope();
}

DART_EXPORT uint8_t* Dart_ScopeAllocate(intptr_t size) {
  Zone* zone;
  Thread* thread = Thread::Current();
  if (thread != NULL) {
    ApiLocalScope* scope = thread->api_top_scope();
    zone = scope->zone();
  } else {
    ApiNativeScope* scope = ApiNativeScope::Current();
    if (scope == NULL) return NULL;
    zone = scope->zone();
  }
  return reinterpret_cast<uint8_t*>(zone->AllocUnsafe(size));
}

// --- Objects ----

DART_EXPORT Dart_Handle Dart_Null() {
  ASSERT(Isolate::Current() != NULL);
  return Api::Null();
}

DART_EXPORT bool Dart_IsNull(Dart_Handle object) {
  TransitionNativeToVM transition(Thread::Current());
  return Api::UnwrapHandle(object) == Object::null();
}

DART_EXPORT Dart_Handle Dart_EmptyString() {
  ASSERT(Isolate::Current() != NULL);
  return Api::EmptyString();
}

DART_EXPORT Dart_Handle Dart_TypeDynamic() {
  DARTSCOPE(Thread::Current());
  CHECK_CALLBACK_STATE(T);
  API_TIMELINE_DURATION(T);
  return Api::NewHandle(T, Type::DynamicType());
}

DART_EXPORT Dart_Handle Dart_TypeVoid() {
  DARTSCOPE(Thread::Current());
  CHECK_CALLBACK_STATE(T);
  API_TIMELINE_DURATION(T);
  return Api::NewHandle(T, Type::VoidType());
}

DART_EXPORT Dart_Handle Dart_TypeNever() {
  DARTSCOPE(Thread::Current());
  CHECK_CALLBACK_STATE(T);
  API_TIMELINE_DURATION(T);
  return Api::NewHandle(T, Type::NeverType());
}

DART_EXPORT Dart_Handle Dart_ObjectEquals(Dart_Handle obj1,
                                          Dart_Handle obj2,
                                          bool* value) {
  DARTSCOPE(Thread::Current());
  CHECK_CALLBACK_STATE(T);
  const Instance& expected =
      Instance::CheckedHandle(Z, Api::UnwrapHandle(obj1));
  const Instance& actual = Instance::CheckedHandle(Z, Api::UnwrapHandle(obj2));
  const Object& result =
      Object::Handle(Z, DartLibraryCalls::Equals(expected, actual));
  if (result.IsBool()) {
    *value = Bool::Cast(result).value();
    return Api::Success();
  } else if (result.IsError()) {
    return Api::NewHandle(T, result.raw());
  } else {
    return Api::NewError("Expected boolean result from ==");
  }
}

// Assumes type is non-null.
static bool InstanceIsType(const Thread* thread,
                           const Instance& instance,
                           const Type& type) {
  ASSERT(!type.IsNull());
  CHECK_CALLBACK_STATE(thread);
  return instance.IsInstanceOf(type, Object::null_type_arguments(),
                               Object::null_type_arguments());
}

DART_EXPORT Dart_Handle Dart_ObjectIsType(Dart_Handle object,
                                          Dart_Handle type,
                                          bool* value) {
  DARTSCOPE(Thread::Current());

  const Type& type_obj = Api::UnwrapTypeHandle(Z, type);
  if (type_obj.IsNull()) {
    *value = false;
    RETURN_TYPE_ERROR(Z, type, Type);
  }
  if (!type_obj.IsFinalized()) {
    return Api::NewError(
        "%s expects argument 'type' to be a fully resolved type.",
        CURRENT_FUNC);
  }
  if (object == Api::Null()) {
    *value = false;
    return Api::Success();
  }
  const Instance& instance = Api::UnwrapInstanceHandle(Z, object);
  if (instance.IsNull()) {
    *value = false;
    RETURN_TYPE_ERROR(Z, object, Instance);
  }
  *value = InstanceIsType(T, instance, type_obj);
  return Api::Success();
}

DART_EXPORT bool Dart_IsInstance(Dart_Handle object) {
  Thread* thread = Thread::Current();
  CHECK_ISOLATE(thread->isolate());
  TransitionNativeToVM transition(thread);
  REUSABLE_OBJECT_HANDLESCOPE(thread);
  Object& ref = thread->ObjectHandle();
  ref = Api::UnwrapHandle(object);
  return ref.IsInstance();
}

DART_EXPORT bool Dart_IsNumber(Dart_Handle object) {
  Thread* thread = Thread::Current();
  CHECK_ISOLATE(thread->isolate());
  TransitionNativeToVM transition(thread);
  return IsNumberClassId(Api::ClassId(object));
}

DART_EXPORT bool Dart_IsInteger(Dart_Handle object) {
  Thread* thread = Thread::Current();
  CHECK_ISOLATE(thread->isolate());
  TransitionNativeToVM transition(thread);
  return IsIntegerClassId(Api::ClassId(object));
}

DART_EXPORT bool Dart_IsDouble(Dart_Handle object) {
  Thread* thread = Thread::Current();
  CHECK_ISOLATE(thread->isolate());
  TransitionNativeToVM transition(thread);
  return Api::ClassId(object) == kDoubleCid;
}

DART_EXPORT bool Dart_IsBoolean(Dart_Handle object) {
  Thread* thread = Thread::Current();
  CHECK_ISOLATE(thread->isolate());
  TransitionNativeToVM transition(thread);
  return Api::ClassId(object) == kBoolCid;
}

DART_EXPORT bool Dart_IsString(Dart_Handle object) {
  Thread* thread = Thread::Current();
  CHECK_ISOLATE(thread->isolate());
  TransitionNativeToVM transition(thread);
  return IsStringClassId(Api::ClassId(object));
}

DART_EXPORT bool Dart_IsStringLatin1(Dart_Handle object) {
  Thread* thread = Thread::Current();
  CHECK_ISOLATE(thread->isolate());
  TransitionNativeToVM transition(thread);
  return IsOneByteStringClassId(Api::ClassId(object));
}

DART_EXPORT bool Dart_IsExternalString(Dart_Handle object) {
  Thread* thread = Thread::Current();
  CHECK_ISOLATE(thread->isolate());
  TransitionNativeToVM transition(thread);
  return IsExternalStringClassId(Api::ClassId(object));
}

DART_EXPORT bool Dart_IsList(Dart_Handle object) {
  DARTSCOPE(Thread::Current());
  if (IsBuiltinListClassId(Api::ClassId(object))) {
    return true;
  }

  const Object& obj = Object::Handle(Z, Api::UnwrapHandle(object));
  return GetListInstance(Z, obj) != Instance::null();
}

DART_EXPORT bool Dart_IsMap(Dart_Handle object) {
  DARTSCOPE(Thread::Current());
  const Object& obj = Object::Handle(Z, Api::UnwrapHandle(object));
  return GetMapInstance(Z, obj) != Instance::null();
}

DART_EXPORT bool Dart_IsLibrary(Dart_Handle object) {
  Thread* thread = Thread::Current();
  CHECK_ISOLATE(thread->isolate());
  TransitionNativeToVM transition(thread);
  return Api::ClassId(object) == kLibraryCid;
}

DART_EXPORT bool Dart_IsType(Dart_Handle handle) {
  Thread* thread = Thread::Current();
  CHECK_ISOLATE(thread->isolate());
  TransitionNativeToVM transition(thread);
  return Api::ClassId(handle) == kTypeCid;
}

DART_EXPORT bool Dart_IsFunction(Dart_Handle handle) {
  Thread* thread = Thread::Current();
  CHECK_ISOLATE(thread->isolate());
  TransitionNativeToVM transition(thread);
  return Api::ClassId(handle) == kFunctionCid;
}

DART_EXPORT bool Dart_IsVariable(Dart_Handle handle) {
  Thread* thread = Thread::Current();
  CHECK_ISOLATE(thread->isolate());
  TransitionNativeToVM transition(thread);
  return Api::ClassId(handle) == kFieldCid;
}

DART_EXPORT bool Dart_IsTypeVariable(Dart_Handle handle) {
  Thread* thread = Thread::Current();
  CHECK_ISOLATE(thread->isolate());
  TransitionNativeToVM transition(thread);
  return Api::ClassId(handle) == kTypeParameterCid;
}

DART_EXPORT bool Dart_IsClosure(Dart_Handle object) {
  Thread* thread = Thread::Current();
  CHECK_ISOLATE(thread->isolate());
  TransitionNativeToVM transition(thread);
  return Api::ClassId(object) == kClosureCid;
}

DART_EXPORT bool Dart_IsTearOff(Dart_Handle object) {
  DARTSCOPE(Thread::Current());
  API_TIMELINE_DURATION(T);
  const Object& obj = Object::Handle(Z, Api::UnwrapHandle(object));
  if (obj.IsClosure()) {
    const Closure& closure = Closure::Cast(obj);
    const Function& func = Function::Handle(Z, closure.function());
    return func.IsImplicitClosureFunction();
  }
  return false;
}

DART_EXPORT bool Dart_IsTypedData(Dart_Handle handle) {
  Thread* thread = Thread::Current();
  CHECK_ISOLATE(thread->isolate());
  TransitionNativeToVM transition(thread);
  intptr_t cid = Api::ClassId(handle);
  return IsTypedDataClassId(cid) || IsExternalTypedDataClassId(cid) ||
         IsTypedDataViewClassId(cid);
}

DART_EXPORT bool Dart_IsByteBuffer(Dart_Handle handle) {
  Thread* thread = Thread::Current();
  CHECK_ISOLATE(thread->isolate());
  TransitionNativeToVM transition(thread);
  return Api::ClassId(handle) == kByteBufferCid;
}

DART_EXPORT bool Dart_IsFuture(Dart_Handle handle) {
  DARTSCOPE(Thread::Current());
  API_TIMELINE_DURATION(T);
  const Object& obj = Object::Handle(Z, Api::UnwrapHandle(handle));
  if (obj.IsInstance()) {
    ObjectStore* object_store = T->isolate()->object_store();
    Type& future_rare_type =
        Type::Handle(Z, object_store->non_nullable_future_rare_type());
    if (future_rare_type.IsNull()) {
      const Class& future_class = Class::Handle(object_store->future_class());
      ASSERT(!future_class.IsNull());
      future_rare_type ^= future_class.RareType();
      object_store->set_non_nullable_future_rare_type(future_rare_type);
    }
    const Class& obj_class = Class::Handle(Z, obj.clazz());
    bool is_future = Class::IsSubtypeOf(
        obj_class, Object::null_type_arguments(), Nullability::kNonNullable,
        future_rare_type, Heap::kNew);
    return is_future;
  }
  return false;
}

// --- Instances ----

DART_EXPORT Dart_Handle Dart_InstanceGetType(Dart_Handle instance) {
  DARTSCOPE(Thread::Current());
  API_TIMELINE_DURATION(T);
  Isolate* I = T->isolate();
  const Object& obj = Object::Handle(Z, Api::UnwrapHandle(instance));
  if (obj.IsNull()) {
    return Api::NewHandle(T, I->object_store()->null_type());
  }
  if (!obj.IsInstance()) {
    RETURN_TYPE_ERROR(Z, instance, Instance);
  }
  const AbstractType& type =
      AbstractType::Handle(Instance::Cast(obj).GetType(Heap::kNew));
  return Api::NewHandle(T, type.Canonicalize());
}

DART_EXPORT Dart_Handle Dart_FunctionName(Dart_Handle function) {
  DARTSCOPE(Thread::Current());
  const Function& func = Api::UnwrapFunctionHandle(Z, function);
  if (func.IsNull()) {
    RETURN_TYPE_ERROR(Z, function, Function);
  }
  return Api::NewHandle(T, func.UserVisibleName());
}

DART_EXPORT Dart_Handle Dart_ClassName(Dart_Handle cls_type) {
  DARTSCOPE(Thread::Current());
  const Type& type_obj = Api::UnwrapTypeHandle(Z, cls_type);
  if (type_obj.IsNull()) {
    RETURN_TYPE_ERROR(Z, cls_type, Type);
  }
  const Class& klass = Class::Handle(Z, type_obj.type_class());
  if (klass.IsNull()) {
    return Api::NewError(
        "cls_type must be a Type object which represents a Class.");
  }
  return Api::NewHandle(T, klass.UserVisibleName());
}

DART_EXPORT Dart_Handle Dart_FunctionOwner(Dart_Handle function) {
  DARTSCOPE(Thread::Current());
  const Function& func = Api::UnwrapFunctionHandle(Z, function);
  if (func.IsNull()) {
    RETURN_TYPE_ERROR(Z, function, Function);
  }
  if (func.IsNonImplicitClosureFunction()) {
    FunctionPtr parent_function = func.parent_function();
    return Api::NewHandle(T, parent_function);
  }
  const Class& owner = Class::Handle(Z, func.Owner());
  ASSERT(!owner.IsNull());
  if (owner.IsTopLevel()) {
// Top-level functions are implemented as members of a hidden class. We hide
// that class here and instead answer the library.
#if defined(DEBUG)
    const Library& lib = Library::Handle(Z, owner.library());
    if (lib.IsNull()) {
      ASSERT(owner.IsDynamicClass() || owner.IsVoidClass() ||
             owner.IsNeverClass());
    }
#endif
    return Api::NewHandle(T, owner.library());
  } else {
    return Api::NewHandle(T, owner.RareType());
  }
}

DART_EXPORT Dart_Handle Dart_FunctionIsStatic(Dart_Handle function,
                                              bool* is_static) {
  DARTSCOPE(Thread::Current());
  if (is_static == NULL) {
    RETURN_NULL_ERROR(is_static);
  }
  const Function& func = Api::UnwrapFunctionHandle(Z, function);
  if (func.IsNull()) {
    RETURN_TYPE_ERROR(Z, function, Function);
  }
  *is_static = func.is_static();
  return Api::Success();
}

DART_EXPORT Dart_Handle Dart_ClosureFunction(Dart_Handle closure) {
  DARTSCOPE(Thread::Current());
  const Instance& closure_obj = Api::UnwrapInstanceHandle(Z, closure);
  if (closure_obj.IsNull() || !closure_obj.IsClosure()) {
    RETURN_TYPE_ERROR(Z, closure, Instance);
  }

  ASSERT(ClassFinalizer::AllClassesFinalized());

  FunctionPtr rf = Closure::Cast(closure_obj).function();
  return Api::NewHandle(T, rf);
}

DART_EXPORT Dart_Handle Dart_ClassLibrary(Dart_Handle cls_type) {
  DARTSCOPE(Thread::Current());
  const Type& type_obj = Api::UnwrapTypeHandle(Z, cls_type);
  const Class& klass = Class::Handle(Z, type_obj.type_class());
  if (klass.IsNull()) {
    return Api::NewError(
        "cls_type must be a Type object which represents a Class.");
  }
  const Library& library = Library::Handle(klass.library());
  if (library.IsNull()) {
    return Dart_Null();
  }
  return Api::NewHandle(Thread::Current(), library.raw());
}

// --- Numbers, Integers and Doubles ----

DART_EXPORT Dart_Handle Dart_IntegerFitsIntoInt64(Dart_Handle integer,
                                                  bool* fits) {
  // Fast path for Smis and Mints.
  Thread* thread = Thread::Current();
  API_TIMELINE_DURATION(thread);
  Isolate* isolate = thread->isolate();
  CHECK_ISOLATE(isolate);
  if (Api::IsSmi(integer)) {
    *fits = true;
    return Api::Success();
  }
  // Slow path for mints and type error.
  DARTSCOPE(thread);
  if (Api::ClassId(integer) == kMintCid) {
    *fits = true;
    return Api::Success();
  }
  const Integer& int_obj = Api::UnwrapIntegerHandle(Z, integer);
  ASSERT(int_obj.IsNull());
  RETURN_TYPE_ERROR(Z, integer, Integer);
}

DART_EXPORT Dart_Handle Dart_IntegerFitsIntoUint64(Dart_Handle integer,
                                                   bool* fits) {
  // Fast path for Smis.
  Thread* thread = Thread::Current();
  Isolate* isolate = thread->isolate();
  CHECK_ISOLATE(isolate);
  API_TIMELINE_DURATION(thread);
  if (Api::IsSmi(integer)) {
    *fits = (Api::SmiValue(integer) >= 0);
    return Api::Success();
  }
  // Slow path for Mints.
  DARTSCOPE(thread);
  const Integer& int_obj = Api::UnwrapIntegerHandle(Z, integer);
  if (int_obj.IsNull()) {
    RETURN_TYPE_ERROR(Z, integer, Integer);
  }
  ASSERT(int_obj.IsMint());
  *fits = !int_obj.IsNegative();
  return Api::Success();
}

DART_EXPORT Dart_Handle Dart_NewInteger(int64_t value) {
  // Fast path for Smis.
  Thread* thread = Thread::Current();
  Isolate* isolate = thread->isolate();
  CHECK_ISOLATE(isolate);
  API_TIMELINE_DURATION(thread);
  DARTSCOPE(thread);
  CHECK_CALLBACK_STATE(thread);
  return Api::NewHandle(thread, Integer::New(value));
}

DART_EXPORT Dart_Handle Dart_NewIntegerFromUint64(uint64_t value) {
  DARTSCOPE(Thread::Current());
  CHECK_CALLBACK_STATE(T);
  API_TIMELINE_DURATION(T);
  if (Integer::IsValueInRange(value)) {
    return Api::NewHandle(T, Integer::NewFromUint64(value));
  }
  return Api::NewError("%s: Cannot create Dart integer from value %" Pu64,
                       CURRENT_FUNC, value);
}

DART_EXPORT Dart_Handle Dart_NewIntegerFromHexCString(const char* str) {
  DARTSCOPE(Thread::Current());
  CHECK_CALLBACK_STATE(T);
  API_TIMELINE_DURATION(T);
  const String& str_obj = String::Handle(Z, String::New(str));
  IntegerPtr integer = Integer::New(str_obj);
  if (integer == Integer::null()) {
    return Api::NewError("%s: Cannot create Dart integer from string %s",
                         CURRENT_FUNC, str);
  }
  return Api::NewHandle(T, integer);
}

DART_EXPORT Dart_Handle Dart_IntegerToInt64(Dart_Handle integer,
                                            int64_t* value) {
  // Fast path for Smis.
  Thread* thread = Thread::Current();
  Isolate* isolate = thread->isolate();
  CHECK_ISOLATE(isolate);
  if (Api::IsSmi(integer)) {
    *value = Api::SmiValue(integer);
    return Api::Success();
  }
  // Slow path for Mints.
  DARTSCOPE(thread);
  const Integer& int_obj = Api::UnwrapIntegerHandle(Z, integer);
  if (int_obj.IsNull()) {
    RETURN_TYPE_ERROR(Z, integer, Integer);
  }
  ASSERT(int_obj.IsMint());
  *value = int_obj.AsInt64Value();
  return Api::Success();
}

DART_EXPORT Dart_Handle Dart_IntegerToUint64(Dart_Handle integer,
                                             uint64_t* value) {
  // Fast path for Smis.
  Thread* thread = Thread::Current();
  Isolate* isolate = thread->isolate();
  CHECK_ISOLATE(isolate);
  if (Api::IsSmi(integer)) {
    intptr_t smi_value = Api::SmiValue(integer);
    if (smi_value >= 0) {
      *value = smi_value;
      return Api::Success();
    }
  }
  // Slow path for Mints.
  DARTSCOPE(thread);
  const Integer& int_obj = Api::UnwrapIntegerHandle(Z, integer);
  if (int_obj.IsNull()) {
    RETURN_TYPE_ERROR(Z, integer, Integer);
  }
  if (int_obj.IsSmi()) {
    ASSERT(int_obj.IsNegative());
  } else {
    ASSERT(int_obj.IsMint());
    if (!int_obj.IsNegative()) {
      *value = int_obj.AsInt64Value();
      return Api::Success();
    }
  }
  return Api::NewError("%s: Integer %s cannot be represented as a uint64_t.",
                       CURRENT_FUNC, int_obj.ToCString());
}

DART_EXPORT Dart_Handle Dart_IntegerToHexCString(Dart_Handle integer,
                                                 const char** value) {
  DARTSCOPE(Thread::Current());
  API_TIMELINE_DURATION(T);
  const Integer& int_obj = Api::UnwrapIntegerHandle(Z, integer);
  if (int_obj.IsNull()) {
    RETURN_TYPE_ERROR(Z, integer, Integer);
  }
  Zone* scope_zone = Api::TopScope(Thread::Current())->zone();
  *value = int_obj.ToHexCString(scope_zone);
  return Api::Success();
}

DART_EXPORT Dart_Handle Dart_NewDouble(double value) {
  DARTSCOPE(Thread::Current());
  CHECK_CALLBACK_STATE(T);
  return Api::NewHandle(T, Double::New(value));
}

DART_EXPORT Dart_Handle Dart_DoubleValue(Dart_Handle double_obj,
                                         double* value) {
  DARTSCOPE(Thread::Current());
  const Double& obj = Api::UnwrapDoubleHandle(Z, double_obj);
  if (obj.IsNull()) {
    RETURN_TYPE_ERROR(Z, double_obj, Double);
  }
  *value = obj.value();
  return Api::Success();
}

DART_EXPORT Dart_Handle Dart_GetStaticMethodClosure(Dart_Handle library,
                                                    Dart_Handle cls_type,
                                                    Dart_Handle function_name) {
  DARTSCOPE(Thread::Current());
  const Library& lib = Api::UnwrapLibraryHandle(Z, library);
  if (lib.IsNull()) {
    RETURN_TYPE_ERROR(Z, library, Library);
  }

  const Type& type_obj = Api::UnwrapTypeHandle(Z, cls_type);
  if (type_obj.IsNull()) {
    RETURN_TYPE_ERROR(Z, cls_type, Type);
  }

  const Class& klass = Class::Handle(Z, type_obj.type_class());
  if (klass.IsNull()) {
    return Api::NewError(
        "cls_type must be a Type object which represents a Class");
  }

  const String& func_name = Api::UnwrapStringHandle(Z, function_name);
  if (func_name.IsNull()) {
    RETURN_TYPE_ERROR(Z, function_name, String);
  }

  Function& func =
      Function::Handle(Z, klass.LookupStaticFunctionAllowPrivate(func_name));
  if (func.IsNull()) {
    return Dart_Null();
  }

  if (!func.is_static()) {
    return Api::NewError("function_name must refer to a static method.");
  }

  if (func.kind() != FunctionLayout::kRegularFunction) {
    return Api::NewError(
        "function_name must be the name of a regular function.");
  }
  func = func.ImplicitClosureFunction();
  if (func.IsNull()) {
    return Dart_Null();
  }

  return Api::NewHandle(T, func.ImplicitStaticClosure());
}

// --- Booleans ----

DART_EXPORT Dart_Handle Dart_True() {
  ASSERT(Isolate::Current() != NULL);
  return Api::True();
}

DART_EXPORT Dart_Handle Dart_False() {
  ASSERT(Isolate::Current() != NULL);
  return Api::False();
}

DART_EXPORT Dart_Handle Dart_NewBoolean(bool value) {
  Isolate* isolate = Isolate::Current();
  CHECK_ISOLATE(isolate);
  return value ? Api::True() : Api::False();
}

DART_EXPORT Dart_Handle Dart_BooleanValue(Dart_Handle boolean_obj,
                                          bool* value) {
  DARTSCOPE(Thread::Current());
  const Bool& obj = Api::UnwrapBoolHandle(Z, boolean_obj);
  if (obj.IsNull()) {
    RETURN_TYPE_ERROR(Z, boolean_obj, Bool);
  }
  *value = obj.value();
  return Api::Success();
}

// --- Strings ---

DART_EXPORT Dart_Handle Dart_StringLength(Dart_Handle str, intptr_t* len) {
  Thread* thread = Thread::Current();
  DARTSCOPE(thread);
  ReusableObjectHandleScope reused_obj_handle(thread);
  const String& str_obj = Api::UnwrapStringHandle(reused_obj_handle, str);
  if (str_obj.IsNull()) {
    RETURN_TYPE_ERROR(thread->zone(), str, String);
  }
  *len = str_obj.Length();
  return Api::Success();
}

DART_EXPORT Dart_Handle Dart_NewStringFromCString(const char* str) {
  DARTSCOPE(Thread::Current());
  API_TIMELINE_DURATION(T);
  if (str == NULL) {
    RETURN_NULL_ERROR(str);
  }
  CHECK_CALLBACK_STATE(T);
  return Api::NewHandle(T, String::New(str));
}

DART_EXPORT Dart_Handle Dart_NewStringFromUTF8(const uint8_t* utf8_array,
                                               intptr_t length) {
  DARTSCOPE(Thread::Current());
  API_TIMELINE_DURATION(T);
  if (utf8_array == NULL && length != 0) {
    RETURN_NULL_ERROR(utf8_array);
  }
  CHECK_LENGTH(length, String::kMaxElements);
  if (!Utf8::IsValid(utf8_array, length)) {
    return Api::NewError("%s expects argument 'str' to be valid UTF-8.",
                         CURRENT_FUNC);
  }
  CHECK_CALLBACK_STATE(T);
  return Api::NewHandle(T, String::FromUTF8(utf8_array, length));
}

DART_EXPORT Dart_Handle Dart_NewStringFromUTF16(const uint16_t* utf16_array,
                                                intptr_t length) {
  DARTSCOPE(Thread::Current());
  if (utf16_array == NULL && length != 0) {
    RETURN_NULL_ERROR(utf16_array);
  }
  CHECK_LENGTH(length, String::kMaxElements);
  CHECK_CALLBACK_STATE(T);
  return Api::NewHandle(T, String::FromUTF16(utf16_array, length));
}

DART_EXPORT Dart_Handle Dart_NewStringFromUTF32(const int32_t* utf32_array,
                                                intptr_t length) {
  DARTSCOPE(Thread::Current());
  API_TIMELINE_DURATION(T);
  if (utf32_array == NULL && length != 0) {
    RETURN_NULL_ERROR(utf32_array);
  }
  CHECK_LENGTH(length, String::kMaxElements);
  CHECK_CALLBACK_STATE(T);
  return Api::NewHandle(T, String::FromUTF32(utf32_array, length));
}

DART_EXPORT Dart_Handle
Dart_NewExternalLatin1String(const uint8_t* latin1_array,
                             intptr_t length,
                             void* peer,
                             intptr_t external_allocation_size,
                             Dart_WeakPersistentHandleFinalizer callback) {
  DARTSCOPE(Thread::Current());
  API_TIMELINE_DURATION(T);
  if (latin1_array == NULL && length != 0) {
    RETURN_NULL_ERROR(latin1_array);
  }
  if (callback == NULL) {
    RETURN_NULL_ERROR(callback);
  }
  CHECK_LENGTH(length, String::kMaxElements);
  CHECK_CALLBACK_STATE(T);
  return Api::NewHandle(
      T,
      String::NewExternal(latin1_array, length, peer, external_allocation_size,
                          callback, T->heap()->SpaceForExternal(length)));
}

DART_EXPORT Dart_Handle
Dart_NewExternalUTF16String(const uint16_t* utf16_array,
                            intptr_t length,
                            void* peer,
                            intptr_t external_allocation_size,
                            Dart_WeakPersistentHandleFinalizer callback) {
  DARTSCOPE(Thread::Current());
  if (utf16_array == NULL && length != 0) {
    RETURN_NULL_ERROR(utf16_array);
  }
  if (callback == NULL) {
    RETURN_NULL_ERROR(callback);
  }
  CHECK_LENGTH(length, String::kMaxElements);
  CHECK_CALLBACK_STATE(T);
  intptr_t bytes = length * sizeof(*utf16_array);
  return Api::NewHandle(
      T,
      String::NewExternal(utf16_array, length, peer, external_allocation_size,
                          callback, T->heap()->SpaceForExternal(bytes)));
}

DART_EXPORT Dart_Handle Dart_StringToCString(Dart_Handle object,
                                             const char** cstr) {
  DARTSCOPE(Thread::Current());
  API_TIMELINE_DURATION(T);
  if (cstr == NULL) {
    RETURN_NULL_ERROR(cstr);
  }
  const String& str_obj = Api::UnwrapStringHandle(Z, object);
  if (str_obj.IsNull()) {
    RETURN_TYPE_ERROR(Z, object, String);
  }
  intptr_t string_length = Utf8::Length(str_obj);
  char* res = Api::TopScope(T)->zone()->Alloc<char>(string_length + 1);
  if (res == NULL) {
    return Api::NewError("Unable to allocate memory");
  }
  const char* string_value = str_obj.ToCString();
  memmove(res, string_value, string_length + 1);
  ASSERT(res[string_length] == '\0');
  *cstr = res;
  return Api::Success();
}

DART_EXPORT Dart_Handle Dart_StringToUTF8(Dart_Handle str,
                                          uint8_t** utf8_array,
                                          intptr_t* length) {
  DARTSCOPE(Thread::Current());
  API_TIMELINE_DURATION(T);
  if (utf8_array == NULL) {
    RETURN_NULL_ERROR(utf8_array);
  }
  if (length == NULL) {
    RETURN_NULL_ERROR(length);
  }
  const String& str_obj = Api::UnwrapStringHandle(Z, str);
  if (str_obj.IsNull()) {
    RETURN_TYPE_ERROR(Z, str, String);
  }
  intptr_t str_len = Utf8::Length(str_obj);
  *utf8_array = Api::TopScope(T)->zone()->Alloc<uint8_t>(str_len);
  if (*utf8_array == NULL) {
    return Api::NewError("Unable to allocate memory");
  }
  str_obj.ToUTF8(*utf8_array, str_len);
  *length = str_len;
  return Api::Success();
}

DART_EXPORT Dart_Handle Dart_StringToLatin1(Dart_Handle str,
                                            uint8_t* latin1_array,
                                            intptr_t* length) {
  DARTSCOPE(Thread::Current());
  API_TIMELINE_DURATION(T);
  if (latin1_array == NULL) {
    RETURN_NULL_ERROR(latin1_array);
  }
  if (length == NULL) {
    RETURN_NULL_ERROR(length);
  }
  const String& str_obj = Api::UnwrapStringHandle(Z, str);
  if (str_obj.IsNull() || !str_obj.IsOneByteString()) {
    RETURN_TYPE_ERROR(Z, str, String);
  }
  intptr_t str_len = str_obj.Length();
  intptr_t copy_len = (str_len > *length) ? *length : str_len;

  // We have already asserted that the string object is a Latin-1 string
  // so we can copy the characters over using a simple loop.
  for (intptr_t i = 0; i < copy_len; i++) {
    latin1_array[i] = str_obj.CharAt(i);
  }
  *length = copy_len;
  return Api::Success();
}

DART_EXPORT Dart_Handle Dart_StringToUTF16(Dart_Handle str,
                                           uint16_t* utf16_array,
                                           intptr_t* length) {
  DARTSCOPE(Thread::Current());
  API_TIMELINE_DURATION(T);
  const String& str_obj = Api::UnwrapStringHandle(Z, str);
  if (str_obj.IsNull()) {
    RETURN_TYPE_ERROR(Z, str, String);
  }
  intptr_t str_len = str_obj.Length();
  intptr_t copy_len = (str_len > *length) ? *length : str_len;
  for (intptr_t i = 0; i < copy_len; i++) {
    utf16_array[i] = str_obj.CharAt(i);
  }
  *length = copy_len;
  return Api::Success();
}

DART_EXPORT Dart_Handle Dart_StringStorageSize(Dart_Handle str,
                                               intptr_t* size) {
  Thread* thread = Thread::Current();
  CHECK_ISOLATE(thread->isolate());
  TransitionNativeToVM transition(thread);
  ReusableObjectHandleScope reused_obj_handle(thread);
  const String& str_obj = Api::UnwrapStringHandle(reused_obj_handle, str);
  if (str_obj.IsNull()) {
    RETURN_TYPE_ERROR(thread->zone(), str, String);
  }
  if (size == NULL) {
    RETURN_NULL_ERROR(size);
  }
  *size = (str_obj.Length() * str_obj.CharSize());
  return Api::Success();
}

DART_EXPORT Dart_Handle Dart_StringGetProperties(Dart_Handle object,
                                                 intptr_t* char_size,
                                                 intptr_t* str_len,
                                                 void** peer) {
  Thread* thread = Thread::Current();
  CHECK_ISOLATE(thread->isolate());
  TransitionNativeToVM transition(thread);
  ReusableObjectHandleScope reused_obj_handle(thread);
  const String& str = Api::UnwrapStringHandle(reused_obj_handle, object);
  if (str.IsNull()) {
    RETURN_TYPE_ERROR(thread->zone(), object, String);
  }
  if (str.IsExternal()) {
    *peer = str.GetPeer();
    ASSERT(*peer != NULL);
  } else {
    NoSafepointScope no_safepoint_scope;
    *peer = thread->isolate()->heap()->GetPeer(str.raw());
  }
  *char_size = str.CharSize();
  *str_len = str.Length();
  return Api::Success();
}

// --- Lists ---

DART_EXPORT Dart_Handle Dart_NewList(intptr_t length) {
  return Dart_NewListOf(Dart_CoreType_Dynamic, length);
}

static TypeArgumentsPtr TypeArgumentsForElementType(
    ObjectStore* store,
    Dart_CoreType_Id element_type_id) {
  switch (element_type_id) {
    case Dart_CoreType_Dynamic:
      return TypeArguments::null();
    case Dart_CoreType_Int:
      return store->type_argument_legacy_int();
    case Dart_CoreType_String:
      return store->type_argument_legacy_string();
  }
  UNREACHABLE();
  return NULL;
}

DART_EXPORT Dart_Handle Dart_NewListOf(Dart_CoreType_Id element_type_id,
                                       intptr_t length) {
  DARTSCOPE(Thread::Current());
  CHECK_LENGTH(length, Array::kMaxElements);
  CHECK_CALLBACK_STATE(T);
  const Array& arr = Array::Handle(Z, Array::New(length));
  if (element_type_id != Dart_CoreType_Dynamic) {
    arr.SetTypeArguments(TypeArguments::Handle(
        Z, TypeArgumentsForElementType(T->isolate()->object_store(),
                                       element_type_id)));
  }
  return Api::NewHandle(T, arr.raw());
}

static bool CanTypeContainNull(const Type& type) {
  return (type.nullability() == Nullability::kLegacy) ||
         (type.nullability() == Nullability::kNullable);
}

DART_EXPORT Dart_Handle Dart_NewListOfType(Dart_Handle element_type,
                                           intptr_t length) {
  DARTSCOPE(Thread::Current());
  CHECK_LENGTH(length, Array::kMaxElements);
  CHECK_CALLBACK_STATE(T);
  const Type& type = Api::UnwrapTypeHandle(Z, element_type);
  if (type.IsNull()) {
    RETURN_TYPE_ERROR(Z, element_type, Type);
  }
  if (!type.IsFinalized()) {
    return Api::NewError(
        "%s expects argument 'type' to be a fully resolved type.",
        CURRENT_FUNC);
  }
  if ((length > 0) && !CanTypeContainNull(type)) {
    return Api::NewError("%s expects argument 'type' to be a nullable type.",
                         CURRENT_FUNC);
  }
  return Api::NewHandle(T, Array::New(length, type));
}

DART_EXPORT Dart_Handle Dart_NewListOfTypeFilled(Dart_Handle element_type,
                                                 Dart_Handle fill_object,
                                                 intptr_t length) {
  DARTSCOPE(Thread::Current());
  CHECK_LENGTH(length, Array::kMaxElements);
  CHECK_CALLBACK_STATE(T);
  const Type& type = Api::UnwrapTypeHandle(Z, element_type);
  if (type.IsNull()) {
    RETURN_TYPE_ERROR(Z, element_type, Type);
  }
  if (!type.IsFinalized()) {
    return Api::NewError(
        "%s expects argument 'type' to be a fully resolved type.",
        CURRENT_FUNC);
  }
  const Instance& instance = Api::UnwrapInstanceHandle(Z, fill_object);
  if (!instance.IsNull() && !InstanceIsType(T, instance, type)) {
    return Api::NewError(
        "%s expects argument 'fill_object' to have the same type as "
        "'element_type'.",
        CURRENT_FUNC);
  }
  if ((length > 0) && instance.IsNull() && !CanTypeContainNull(type)) {
    return Api::NewError(
        "%s expects argument 'fill_object' to be non-null for a non-nullable "
        "'element_type'.",
        CURRENT_FUNC);
  }
  Array& arr = Array::Handle(Z, Array::New(length, type));
  for (intptr_t i = 0; i < arr.Length(); ++i) {
    arr.SetAt(i, instance);
  }
  return Api::NewHandle(T, arr.raw());
}

#define GET_LIST_LENGTH(zone, type, obj, len)                                  \
  type& array = type::Handle(zone);                                            \
  array ^= obj.raw();                                                          \
  *len = array.Length();                                                       \
  return Api::Success();

DART_EXPORT Dart_Handle Dart_ListLength(Dart_Handle list, intptr_t* len) {
  DARTSCOPE(Thread::Current());
  const Object& obj = Object::Handle(Z, Api::UnwrapHandle(list));
  if (obj.IsError()) {
    // Pass through errors.
    return list;
  }
  if (obj.IsTypedData()) {
    GET_LIST_LENGTH(Z, TypedData, obj, len);
  }
  if (obj.IsArray()) {
    GET_LIST_LENGTH(Z, Array, obj, len);
  }
  if (obj.IsGrowableObjectArray()) {
    GET_LIST_LENGTH(Z, GrowableObjectArray, obj, len);
  }
  if (obj.IsExternalTypedData()) {
    GET_LIST_LENGTH(Z, ExternalTypedData, obj, len);
  }
  CHECK_CALLBACK_STATE(T);

  // Now check and handle a dart object that implements the List interface.
  const Instance& instance = Instance::Handle(Z, GetListInstance(Z, obj));
  if (instance.IsNull()) {
    return Api::NewArgumentError(
        "Object does not implement the List interface");
  }
  const String& name = String::Handle(Z, Field::GetterName(Symbols::Length()));
  const int kTypeArgsLen = 0;
  const int kNumArgs = 1;
  ArgumentsDescriptor args_desc(
      Array::Handle(Z, ArgumentsDescriptor::NewBoxed(kTypeArgsLen, kNumArgs)));
  const Function& function =
      Function::Handle(Z, Resolver::ResolveDynamic(instance, name, args_desc));
  if (function.IsNull()) {
    return Api::NewArgumentError("List object does not have a 'length' field.");
  }

  const Array& args = Array::Handle(Z, Array::New(kNumArgs));
  args.SetAt(0, instance);  // Set up the receiver as the first argument.
  const Object& retval =
      Object::Handle(Z, DartEntry::InvokeFunction(function, args));
  if (retval.IsSmi()) {
    *len = Smi::Cast(retval).Value();
    return Api::Success();
  } else if (retval.IsMint()) {
    int64_t mint_value = Mint::Cast(retval).value();
    if (mint_value >= kIntptrMin && mint_value <= kIntptrMax) {
      *len = static_cast<intptr_t>(mint_value);
      return Api::Success();
    }
    return Api::NewError(
        "Length of List object is greater than the "
        "maximum value that 'len' parameter can hold");
  } else if (retval.IsError()) {
    return Api::NewHandle(T, retval.raw());
  } else {
    return Api::NewError("Length of List object is not an integer");
  }
}

#define GET_LIST_ELEMENT(thread, type, obj, index)                             \
  const type& array_obj = type::Cast(obj);                                     \
  if ((index >= 0) && (index < array_obj.Length())) {                          \
    return Api::NewHandle(thread, array_obj.At(index));                        \
  }                                                                            \
  return Api::NewError("Invalid index passed in to access list element");

DART_EXPORT Dart_Handle Dart_ListGetAt(Dart_Handle list, intptr_t index) {
  DARTSCOPE(Thread::Current());
  const Object& obj = Object::Handle(Z, Api::UnwrapHandle(list));
  if (obj.IsArray()) {
    GET_LIST_ELEMENT(T, Array, obj, index);
  } else if (obj.IsGrowableObjectArray()) {
    GET_LIST_ELEMENT(T, GrowableObjectArray, obj, index);
  } else if (obj.IsError()) {
    return list;
  } else {
    CHECK_CALLBACK_STATE(T);
    // Check and handle a dart object that implements the List interface.
    const Instance& instance = Instance::Handle(Z, GetListInstance(Z, obj));
    if (!instance.IsNull()) {
      return Api::NewHandle(T,
                            Send1Arg(instance, Symbols::IndexToken(),
                                     Instance::Handle(Z, Integer::New(index))));
    }
    return Api::NewArgumentError(
        "Object does not implement the 'List' interface");
  }
}

#define GET_LIST_RANGE(thread, type, obj, offset, length)                      \
  const type& array_obj = type::Cast(obj);                                     \
  if ((offset >= 0) && (offset + length <= array_obj.Length())) {              \
    for (intptr_t index = 0; index < length; ++index) {                        \
      result[index] = Api::NewHandle(thread, array_obj.At(index + offset));    \
    }                                                                          \
    return Api::Success();                                                     \
  }                                                                            \
  return Api::NewError("Invalid offset/length passed in to access list");

DART_EXPORT Dart_Handle Dart_ListGetRange(Dart_Handle list,
                                          intptr_t offset,
                                          intptr_t length,
                                          Dart_Handle* result) {
  DARTSCOPE(Thread::Current());
  if (result == NULL) {
    RETURN_NULL_ERROR(result);
  }
  const Object& obj = Object::Handle(Z, Api::UnwrapHandle(list));
  if (obj.IsArray()) {
    GET_LIST_RANGE(T, Array, obj, offset, length);
  } else if (obj.IsGrowableObjectArray()) {
    GET_LIST_RANGE(T, GrowableObjectArray, obj, offset, length);
  } else if (obj.IsError()) {
    return list;
  } else {
    CHECK_CALLBACK_STATE(T);
    // Check and handle a dart object that implements the List interface.
    const Instance& instance = Instance::Handle(Z, GetListInstance(Z, obj));
    if (!instance.IsNull()) {
      const intptr_t kTypeArgsLen = 0;
      const intptr_t kNumArgs = 2;
      ArgumentsDescriptor args_desc(
          Array::Handle(ArgumentsDescriptor::NewBoxed(kTypeArgsLen, kNumArgs)));
      const Function& function = Function::Handle(
          Z, Resolver::ResolveDynamic(instance, Symbols::AssignIndexToken(),
                                      args_desc));
      if (!function.IsNull()) {
        const Array& args = Array::Handle(Array::New(kNumArgs));
        args.SetAt(0, instance);
        Instance& index = Instance::Handle(Z);
        for (intptr_t i = 0; i < length; ++i) {
          index = Integer::New(i);
          args.SetAt(1, index);
          Dart_Handle value =
              Api::NewHandle(T, DartEntry::InvokeFunction(function, args));
          if (Api::IsError(value)) return value;
          result[i] = value;
        }
        return Api::Success();
      }
    }
    return Api::NewArgumentError(
        "Object does not implement the 'List' interface");
  }
}

#define SET_LIST_ELEMENT(type, obj, index, value)                              \
  const type& array = type::Cast(obj);                                         \
  const Object& value_obj = Object::Handle(Z, Api::UnwrapHandle(value));       \
  if (!value_obj.IsNull() && !value_obj.IsInstance()) {                        \
    RETURN_TYPE_ERROR(Z, value, Instance);                                     \
  }                                                                            \
  if ((index >= 0) && (index < array.Length())) {                              \
    array.SetAt(index, value_obj);                                             \
    return Api::Success();                                                     \
  }                                                                            \
  return Api::NewError("Invalid index passed in to set list element");

DART_EXPORT Dart_Handle Dart_ListSetAt(Dart_Handle list,
                                       intptr_t index,
                                       Dart_Handle value) {
  DARTSCOPE(Thread::Current());
  const Object& obj = Object::Handle(Z, Api::UnwrapHandle(list));
  // If the list is immutable we call into Dart for the indexed setter to
  // get the unsupported operation exception as the result.
  if (obj.IsArray() && !Array::Cast(obj).IsImmutable()) {
    SET_LIST_ELEMENT(Array, obj, index, value);
  } else if (obj.IsGrowableObjectArray()) {
    SET_LIST_ELEMENT(GrowableObjectArray, obj, index, value);
  } else if (obj.IsError()) {
    return list;
  } else {
    CHECK_CALLBACK_STATE(T);

    // Check and handle a dart object that implements the List interface.
    const Instance& instance = Instance::Handle(Z, GetListInstance(Z, obj));
    if (!instance.IsNull()) {
      const intptr_t kTypeArgsLen = 0;
      const intptr_t kNumArgs = 3;
      ArgumentsDescriptor args_desc(
          Array::Handle(ArgumentsDescriptor::NewBoxed(kTypeArgsLen, kNumArgs)));
      const Function& function = Function::Handle(
          Z, Resolver::ResolveDynamic(instance, Symbols::AssignIndexToken(),
                                      args_desc));
      if (!function.IsNull()) {
        const Integer& index_obj = Integer::Handle(Z, Integer::New(index));
        const Object& value_obj = Object::Handle(Z, Api::UnwrapHandle(value));
        if (!value_obj.IsNull() && !value_obj.IsInstance()) {
          RETURN_TYPE_ERROR(Z, value, Instance);
        }
        const Array& args = Array::Handle(Z, Array::New(kNumArgs));
        args.SetAt(0, instance);
        args.SetAt(1, index_obj);
        args.SetAt(2, value_obj);
        return Api::NewHandle(T, DartEntry::InvokeFunction(function, args));
      }
    }
    return Api::NewArgumentError(
        "Object does not implement the 'List' interface");
  }
}

static ObjectPtr ResolveConstructor(const char* current_func,
                                    const Class& cls,
                                    const String& class_name,
                                    const String& dotted_name,
                                    int num_args);

static ObjectPtr ThrowArgumentError(const char* exception_message) {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  // Lookup the class ArgumentError in dart:core.
  const String& lib_url = String::Handle(String::New("dart:core"));
  const String& class_name = String::Handle(String::New("ArgumentError"));
  const Library& lib =
      Library::Handle(zone, Library::LookupLibrary(thread, lib_url));
  if (lib.IsNull()) {
    const String& message = String::Handle(String::NewFormatted(
        "%s: library '%s' not found.", CURRENT_FUNC, lib_url.ToCString()));
    return ApiError::New(message);
  }
  const Class& cls =
      Class::Handle(zone, lib.LookupClassAllowPrivate(class_name));
  ASSERT(!cls.IsNull());
  Object& result = Object::Handle(zone);
  String& dot_name = String::Handle(String::New("."));
  String& constr_name = String::Handle(String::Concat(class_name, dot_name));
  result = ResolveConstructor(CURRENT_FUNC, cls, class_name, constr_name, 1);
  if (result.IsError()) return result.raw();
  ASSERT(result.IsFunction());
  Function& constructor = Function::Handle(zone);
  constructor ^= result.raw();
  if (!constructor.IsGenerativeConstructor()) {
    const String& message = String::Handle(
        String::NewFormatted("%s: class '%s' is not a constructor.",
                             CURRENT_FUNC, class_name.ToCString()));
    return ApiError::New(message);
  }
  Instance& exception = Instance::Handle(zone);
  exception = Instance::New(cls);
  const Array& args = Array::Handle(zone, Array::New(2));
  args.SetAt(0, exception);
  args.SetAt(1, String::Handle(String::New(exception_message)));
  result = DartEntry::InvokeFunction(constructor, args);
  if (result.IsError()) return result.raw();
  ASSERT(result.IsNull());

  if (thread->top_exit_frame_info() == 0) {
    // There are no dart frames on the stack so it would be illegal to
    // throw an exception here.
    const String& message = String::Handle(
        String::New("No Dart frames on stack, cannot throw exception"));
    return ApiError::New(message);
  }
  // Unwind all the API scopes till the exit frame before throwing an
  // exception.
  const Instance* saved_exception;
  {
    NoSafepointScope no_safepoint;
    InstancePtr raw_exception = exception.raw();
    thread->UnwindScopes(thread->top_exit_frame_info());
    saved_exception = &Instance::Handle(raw_exception);
  }
  Exceptions::Throw(thread, *saved_exception);
  const String& message =
      String::Handle(String::New("Exception was not thrown, internal error"));
  return ApiError::New(message);
}

// TODO(sgjesse): value should always be smaller then 0xff. Add error handling.
#define GET_LIST_ELEMENT_AS_BYTES(type, obj, native_array, offset, length)     \
  const type& array = type::Cast(obj);                                         \
  if (Utils::RangeCheck(offset, length, array.Length())) {                     \
    Object& element = Object::Handle(Z);                                       \
    for (int i = 0; i < length; i++) {                                         \
      element = array.At(offset + i);                                          \
      if (!element.IsInteger()) {                                              \
        return Api::NewHandle(                                                 \
            T, ThrowArgumentError("List contains non-int elements"));          \
      }                                                                        \
      const Integer& integer = Integer::Cast(element);                         \
      native_array[i] = static_cast<uint8_t>(integer.AsInt64Value() & 0xff);   \
      ASSERT(integer.AsInt64Value() <= 0xff);                                  \
    }                                                                          \
    return Api::Success();                                                     \
  }                                                                            \
  return Api::NewError("Invalid length passed in to access array elements");

template <typename T>
static Dart_Handle CopyBytes(const T& array,
                             intptr_t offset,
                             uint8_t* native_array,
                             intptr_t length) {
  ASSERT(array.ElementSizeInBytes() == 1);
  NoSafepointScope no_safepoint;
  memmove(native_array, reinterpret_cast<uint8_t*>(array.DataAddr(offset)),
          length);
  return Api::Success();
}

DART_EXPORT Dart_Handle Dart_ListGetAsBytes(Dart_Handle list,
                                            intptr_t offset,
                                            uint8_t* native_array,
                                            intptr_t length) {
  DARTSCOPE(Thread::Current());
  const Object& obj = Object::Handle(Z, Api::UnwrapHandle(list));
  if (obj.IsTypedData()) {
    const TypedData& array = TypedData::Cast(obj);
    if (array.ElementSizeInBytes() == 1) {
      if (!Utils::RangeCheck(offset, length, array.Length())) {
        return Api::NewError(
            "Invalid length passed in to access list elements");
      }
      return CopyBytes(array, offset, native_array, length);
    }
  }
  if (obj.IsExternalTypedData()) {
    const ExternalTypedData& external_array = ExternalTypedData::Cast(obj);
    if (external_array.ElementSizeInBytes() == 1) {
      if (!Utils::RangeCheck(offset, length, external_array.Length())) {
        return Api::NewError(
            "Invalid length passed in to access list elements");
      }
      return CopyBytes(external_array, offset, native_array, length);
    }
  }
  if (IsTypedDataViewClassId(obj.GetClassId())) {
    const auto& view = TypedDataView::Cast(obj);
    if (view.ElementSizeInBytes() == 1) {
      const intptr_t view_length = Smi::Value(view.length());
      if (!Utils::RangeCheck(offset, length, view_length)) {
        return Api::NewError(
            "Invalid length passed in to access list elements");
      }
      const auto& data = Instance::Handle(view.typed_data());
      if (data.IsTypedData()) {
        const TypedData& array = TypedData::Cast(data);
        if (array.ElementSizeInBytes() == 1) {
          const intptr_t data_offset =
              Smi::Value(view.offset_in_bytes()) + offset;
          // Range check already performed on the view object.
          ASSERT(Utils::RangeCheck(data_offset, length, array.Length()));
          return CopyBytes(array, data_offset, native_array, length);
        }
      }
    }
  }
  if (obj.IsArray()) {
    GET_LIST_ELEMENT_AS_BYTES(Array, obj, native_array, offset, length);
  }
  if (obj.IsGrowableObjectArray()) {
    GET_LIST_ELEMENT_AS_BYTES(GrowableObjectArray, obj, native_array, offset,
                              length);
  }
  if (obj.IsError()) {
    return list;
  }
  CHECK_CALLBACK_STATE(T);

  // Check and handle a dart object that implements the List interface.
  const Instance& instance = Instance::Handle(Z, GetListInstance(Z, obj));
  if (!instance.IsNull()) {
    const int kTypeArgsLen = 0;
    const int kNumArgs = 2;
    ArgumentsDescriptor args_desc(
        Array::Handle(ArgumentsDescriptor::NewBoxed(kTypeArgsLen, kNumArgs)));
    const Function& function = Function::Handle(
        Z,
        Resolver::ResolveDynamic(instance, Symbols::IndexToken(), args_desc));
    if (!function.IsNull()) {
      Object& result = Object::Handle(Z);
      Integer& intobj = Integer::Handle(Z);
      const Array& args = Array::Handle(Z, Array::New(kNumArgs));
      args.SetAt(0, instance);  // Set up the receiver as the first argument.
      for (int i = 0; i < length; i++) {
        HANDLESCOPE(T);
        intobj = Integer::New(offset + i);
        args.SetAt(1, intobj);
        result = DartEntry::InvokeFunction(function, args);
        if (result.IsError()) {
          return Api::NewHandle(T, result.raw());
        }
        if (!result.IsInteger()) {
          return Api::NewError(
              "%s expects the argument 'list' to be "
              "a List of int",
              CURRENT_FUNC);
        }
        const Integer& integer_result = Integer::Cast(result);
        ASSERT(integer_result.AsInt64Value() <= 0xff);
        // TODO(hpayer): value should always be smaller then 0xff. Add error
        // handling.
        native_array[i] =
            static_cast<uint8_t>(integer_result.AsInt64Value() & 0xff);
      }
      return Api::Success();
    }
  }
  return Api::NewArgumentError(
      "Object does not implement the 'List' interface");
}

#define SET_LIST_ELEMENT_AS_BYTES(type, obj, native_array, offset, length)     \
  const type& array = type::Cast(obj);                                         \
  Integer& integer = Integer::Handle(Z);                                       \
  if (Utils::RangeCheck(offset, length, array.Length())) {                     \
    for (int i = 0; i < length; i++) {                                         \
      integer = Integer::New(native_array[i]);                                 \
      array.SetAt(offset + i, integer);                                        \
    }                                                                          \
    return Api::Success();                                                     \
  }                                                                            \
  return Api::NewError("Invalid length passed in to set array elements");

DART_EXPORT Dart_Handle Dart_ListSetAsBytes(Dart_Handle list,
                                            intptr_t offset,
                                            const uint8_t* native_array,
                                            intptr_t length) {
  DARTSCOPE(Thread::Current());
  const Object& obj = Object::Handle(Z, Api::UnwrapHandle(list));
  if (obj.IsTypedData()) {
    const TypedData& array = TypedData::Cast(obj);
    if (array.ElementSizeInBytes() == 1) {
      if (Utils::RangeCheck(offset, length, array.Length())) {
        NoSafepointScope no_safepoint;
        memmove(reinterpret_cast<uint8_t*>(array.DataAddr(offset)),
                native_array, length);
        return Api::Success();
      }
      return Api::NewError("Invalid length passed in to access list elements");
    }
  }
  if (obj.IsArray() && !Array::Cast(obj).IsImmutable()) {
    // If the list is immutable we call into Dart for the indexed setter to
    // get the unsupported operation exception as the result.
    SET_LIST_ELEMENT_AS_BYTES(Array, obj, native_array, offset, length);
  }
  if (obj.IsGrowableObjectArray()) {
    SET_LIST_ELEMENT_AS_BYTES(GrowableObjectArray, obj, native_array, offset,
                              length);
  }
  if (obj.IsError()) {
    return list;
  }
  CHECK_CALLBACK_STATE(T);

  // Check and handle a dart object that implements the List interface.
  const Instance& instance = Instance::Handle(Z, GetListInstance(Z, obj));
  if (!instance.IsNull()) {
    const int kTypeArgsLen = 0;
    const int kNumArgs = 3;
    ArgumentsDescriptor args_desc(Array::Handle(
        Z, ArgumentsDescriptor::NewBoxed(kTypeArgsLen, kNumArgs)));
    const Function& function = Function::Handle(
        Z, Resolver::ResolveDynamic(instance, Symbols::AssignIndexToken(),
                                    args_desc));
    if (!function.IsNull()) {
      Integer& indexobj = Integer::Handle(Z);
      Integer& valueobj = Integer::Handle(Z);
      const Array& args = Array::Handle(Z, Array::New(kNumArgs));
      args.SetAt(0, instance);  // Set up the receiver as the first argument.
      for (int i = 0; i < length; i++) {
        indexobj = Integer::New(offset + i);
        valueobj = Integer::New(native_array[i]);
        args.SetAt(1, indexobj);
        args.SetAt(2, valueobj);
        const Object& result =
            Object::Handle(Z, DartEntry::InvokeFunction(function, args));
        if (result.IsError()) {
          return Api::NewHandle(T, result.raw());
        }
      }
      return Api::Success();
    }
  }
  return Api::NewArgumentError(
      "Object does not implement the 'List' interface");
}

// --- Maps ---

DART_EXPORT Dart_Handle Dart_MapGetAt(Dart_Handle map, Dart_Handle key) {
  DARTSCOPE(Thread::Current());
  CHECK_CALLBACK_STATE(T);
  const Object& obj = Object::Handle(Z, Api::UnwrapHandle(map));
  const Instance& instance = Instance::Handle(Z, GetMapInstance(Z, obj));
  if (!instance.IsNull()) {
    const Object& key_obj = Object::Handle(Api::UnwrapHandle(key));
    if (!(key_obj.IsInstance() || key_obj.IsNull())) {
      return Api::NewError("Key is not an instance");
    }
    return Api::NewHandle(
        T, Send1Arg(instance, Symbols::IndexToken(), Instance::Cast(key_obj)));
  }
  return Api::NewArgumentError("Object does not implement the 'Map' interface");
}

DART_EXPORT Dart_Handle Dart_MapContainsKey(Dart_Handle map, Dart_Handle key) {
  DARTSCOPE(Thread::Current());
  CHECK_CALLBACK_STATE(T);
  const Object& obj = Object::Handle(Z, Api::UnwrapHandle(map));
  const Instance& instance = Instance::Handle(Z, GetMapInstance(Z, obj));
  if (!instance.IsNull()) {
    const Object& key_obj = Object::Handle(Z, Api::UnwrapHandle(key));
    if (!(key_obj.IsInstance() || key_obj.IsNull())) {
      return Api::NewError("Key is not an instance");
    }
    return Api::NewHandle(
        T, Send1Arg(instance, String::Handle(Z, String::New("containsKey")),
                    Instance::Cast(key_obj)));
  }
  return Api::NewArgumentError("Object does not implement the 'Map' interface");
}

DART_EXPORT Dart_Handle Dart_MapKeys(Dart_Handle map) {
  DARTSCOPE(Thread::Current());
  CHECK_CALLBACK_STATE(T);
  Object& obj = Object::Handle(Z, Api::UnwrapHandle(map));
  Instance& instance = Instance::Handle(Z, GetMapInstance(Z, obj));
  if (!instance.IsNull()) {
    const Object& iterator = Object::Handle(
        Send0Arg(instance, String::Handle(Z, String::New("get:keys"))));
    if (!iterator.IsInstance()) {
      return Api::NewHandle(T, iterator.raw());
    }
    return Api::NewHandle(T, Send0Arg(Instance::Cast(iterator),
                                      String::Handle(String::New("toList"))));
  }
  return Api::NewArgumentError("Object does not implement the 'Map' interface");
}

// --- Typed Data ---

// Helper method to get the type of a TypedData object.
static Dart_TypedData_Type GetType(intptr_t class_id) {
  Dart_TypedData_Type type;
  switch (class_id) {
    case kByteDataViewCid:
      type = Dart_TypedData_kByteData;
      break;
    case kTypedDataInt8ArrayCid:
    case kTypedDataInt8ArrayViewCid:
    case kExternalTypedDataInt8ArrayCid:
      type = Dart_TypedData_kInt8;
      break;
    case kTypedDataUint8ArrayCid:
    case kTypedDataUint8ArrayViewCid:
    case kExternalTypedDataUint8ArrayCid:
      type = Dart_TypedData_kUint8;
      break;
    case kTypedDataUint8ClampedArrayCid:
    case kTypedDataUint8ClampedArrayViewCid:
    case kExternalTypedDataUint8ClampedArrayCid:
      type = Dart_TypedData_kUint8Clamped;
      break;
    case kTypedDataInt16ArrayCid:
    case kTypedDataInt16ArrayViewCid:
    case kExternalTypedDataInt16ArrayCid:
      type = Dart_TypedData_kInt16;
      break;
    case kTypedDataUint16ArrayCid:
    case kTypedDataUint16ArrayViewCid:
    case kExternalTypedDataUint16ArrayCid:
      type = Dart_TypedData_kUint16;
      break;
    case kTypedDataInt32ArrayCid:
    case kTypedDataInt32ArrayViewCid:
    case kExternalTypedDataInt32ArrayCid:
      type = Dart_TypedData_kInt32;
      break;
    case kTypedDataUint32ArrayCid:
    case kTypedDataUint32ArrayViewCid:
    case kExternalTypedDataUint32ArrayCid:
      type = Dart_TypedData_kUint32;
      break;
    case kTypedDataInt64ArrayCid:
    case kTypedDataInt64ArrayViewCid:
    case kExternalTypedDataInt64ArrayCid:
      type = Dart_TypedData_kInt64;
      break;
    case kTypedDataUint64ArrayCid:
    case kTypedDataUint64ArrayViewCid:
    case kExternalTypedDataUint64ArrayCid:
      type = Dart_TypedData_kUint64;
      break;
    case kTypedDataFloat32ArrayCid:
    case kTypedDataFloat32ArrayViewCid:
    case kExternalTypedDataFloat32ArrayCid:
      type = Dart_TypedData_kFloat32;
      break;
    case kTypedDataFloat64ArrayCid:
    case kTypedDataFloat64ArrayViewCid:
    case kExternalTypedDataFloat64ArrayCid:
      type = Dart_TypedData_kFloat64;
      break;
    case kTypedDataFloat32x4ArrayCid:
    case kTypedDataFloat32x4ArrayViewCid:
    case kExternalTypedDataFloat32x4ArrayCid:
      type = Dart_TypedData_kFloat32x4;
      break;
    default:
      type = Dart_TypedData_kInvalid;
      break;
  }
  return type;
}

DART_EXPORT Dart_TypedData_Type Dart_GetTypeOfTypedData(Dart_Handle object) {
  Thread* thread = Thread::Current();
  API_TIMELINE_DURATION(thread);
  TransitionNativeToVM transition(thread);
  intptr_t class_id = Api::ClassId(object);
  if (IsTypedDataClassId(class_id) || IsTypedDataViewClassId(class_id)) {
    return GetType(class_id);
  }
  return Dart_TypedData_kInvalid;
}

DART_EXPORT Dart_TypedData_Type
Dart_GetTypeOfExternalTypedData(Dart_Handle object) {
  Thread* thread = Thread::Current();
  API_TIMELINE_DURATION(thread);
  TransitionNativeToVM transition(thread);
  intptr_t class_id = Api::ClassId(object);
  if (IsExternalTypedDataClassId(class_id)) {
    return GetType(class_id);
  }
  if (IsTypedDataViewClassId(class_id)) {
    // Check if data object of the view is external.
    Zone* zone = thread->zone();
    const auto& view_obj = Api::UnwrapTypedDataViewHandle(zone, object);
    ASSERT(!view_obj.IsNull());
    const auto& data_obj = Instance::Handle(zone, view_obj.typed_data());
    if (ExternalTypedData::IsExternalTypedData(data_obj)) {
      return GetType(class_id);
    }
  }
  return Dart_TypedData_kInvalid;
}

static ObjectPtr GetByteDataConstructor(Thread* thread,
                                        const String& constructor_name,
                                        intptr_t num_args) {
  const Library& lib =
      Library::Handle(thread->isolate()->object_store()->typed_data_library());
  ASSERT(!lib.IsNull());
  const Class& cls = Class::Handle(
      thread->zone(), lib.LookupClassAllowPrivate(Symbols::ByteData()));
  ASSERT(!cls.IsNull());
  return ResolveConstructor(CURRENT_FUNC, cls, Symbols::ByteData(),
                            constructor_name, num_args);
}

static Dart_Handle NewByteData(Thread* thread, intptr_t length) {
  CHECK_LENGTH(length, TypedData::MaxElements(kTypedDataInt8ArrayCid));
  Zone* zone = thread->zone();
  Object& result = Object::Handle(zone);
  result = GetByteDataConstructor(thread, Symbols::ByteDataDot(), 1);
  ASSERT(!result.IsNull());
  ASSERT(result.IsFunction());
  const Function& factory = Function::Cast(result);
  ASSERT(!factory.IsGenerativeConstructor());

  // Create the argument list.
  const Array& args = Array::Handle(zone, Array::New(2));
  // Factories get type arguments.
  args.SetAt(0, Object::null_type_arguments());
  args.SetAt(1, Smi::Handle(zone, Smi::New(length)));

  // Invoke the constructor and return the new object.
  result = DartEntry::InvokeFunction(factory, args);
  ASSERT(result.IsInstance() || result.IsNull() || result.IsError());
  return Api::NewHandle(thread, result.raw());
}

static Dart_Handle NewTypedData(Thread* thread, intptr_t cid, intptr_t length) {
  CHECK_LENGTH(length, TypedData::MaxElements(cid));
  return Api::NewHandle(thread, TypedData::New(cid, length));
}

static Dart_Handle NewExternalTypedData(
    Thread* thread,
    intptr_t cid,
    void* data,
    intptr_t length,
    void* peer,
    intptr_t external_allocation_size,
    Dart_WeakPersistentHandleFinalizer callback) {
  CHECK_LENGTH(length, ExternalTypedData::MaxElements(cid));
  Zone* zone = thread->zone();
  intptr_t bytes = length * ExternalTypedData::ElementSizeInBytes(cid);
  const ExternalTypedData& result = ExternalTypedData::Handle(
      zone,
      ExternalTypedData::New(cid, reinterpret_cast<uint8_t*>(data), length,
                             thread->heap()->SpaceForExternal(bytes)));
  if (callback != NULL) {
    AllocateFinalizableHandle(thread, result, peer, external_allocation_size,
                              callback);
  }
  return Api::NewHandle(thread, result.raw());
}

static Dart_Handle NewExternalByteData(
    Thread* thread,
    void* data,
    intptr_t length,
    void* peer,
    intptr_t external_allocation_size,
    Dart_WeakPersistentHandleFinalizer callback) {
  Zone* zone = thread->zone();
  Dart_Handle ext_data =
      NewExternalTypedData(thread, kExternalTypedDataUint8ArrayCid, data,
                           length, peer, external_allocation_size, callback);
  if (Api::IsError(ext_data)) {
    return ext_data;
  }
  Object& result = Object::Handle(zone);
  result = GetByteDataConstructor(thread, Symbols::ByteDataDot_view(), 3);
  ASSERT(!result.IsNull());
  ASSERT(result.IsFunction());
  const Function& factory = Function::Cast(result);
  ASSERT(!factory.IsGenerativeConstructor());

  // Create the argument list.
  const intptr_t num_args = 3;
  const Array& args = Array::Handle(zone, Array::New(num_args + 1));
  // Factories get type arguments.
  args.SetAt(0, Object::null_type_arguments());
  const ExternalTypedData& array =
      Api::UnwrapExternalTypedDataHandle(zone, ext_data);
  args.SetAt(1, array);
  Smi& smi = Smi::Handle(zone);
  smi = Smi::New(0);
  args.SetAt(2, smi);
  smi = Smi::New(length);
  args.SetAt(3, smi);

  // Invoke the constructor and return the new object.
  result = DartEntry::InvokeFunction(factory, args);
  ASSERT(result.IsNull() || result.IsInstance() || result.IsError());
  return Api::NewHandle(thread, result.raw());
}

DART_EXPORT Dart_Handle Dart_NewTypedData(Dart_TypedData_Type type,
                                          intptr_t length) {
  DARTSCOPE(Thread::Current());
  CHECK_CALLBACK_STATE(T);
  switch (type) {
    case Dart_TypedData_kByteData:
      return NewByteData(T, length);
    case Dart_TypedData_kInt8:
      return NewTypedData(T, kTypedDataInt8ArrayCid, length);
    case Dart_TypedData_kUint8:
      return NewTypedData(T, kTypedDataUint8ArrayCid, length);
    case Dart_TypedData_kUint8Clamped:
      return NewTypedData(T, kTypedDataUint8ClampedArrayCid, length);
    case Dart_TypedData_kInt16:
      return NewTypedData(T, kTypedDataInt16ArrayCid, length);
    case Dart_TypedData_kUint16:
      return NewTypedData(T, kTypedDataUint16ArrayCid, length);
    case Dart_TypedData_kInt32:
      return NewTypedData(T, kTypedDataInt32ArrayCid, length);
    case Dart_TypedData_kUint32:
      return NewTypedData(T, kTypedDataUint32ArrayCid, length);
    case Dart_TypedData_kInt64:
      return NewTypedData(T, kTypedDataInt64ArrayCid, length);
    case Dart_TypedData_kUint64:
      return NewTypedData(T, kTypedDataUint64ArrayCid, length);
    case Dart_TypedData_kFloat32:
      return NewTypedData(T, kTypedDataFloat32ArrayCid, length);
    case Dart_TypedData_kFloat64:
      return NewTypedData(T, kTypedDataFloat64ArrayCid, length);
    case Dart_TypedData_kFloat32x4:
      return NewTypedData(T, kTypedDataFloat32x4ArrayCid, length);
    default:
      return Api::NewError("%s expects argument 'type' to be of 'TypedData'",
                           CURRENT_FUNC);
  }
  UNREACHABLE();
  return Api::Null();
}

DART_EXPORT Dart_Handle Dart_NewExternalTypedData(Dart_TypedData_Type type,
                                                  void* data,
                                                  intptr_t length) {
  return Dart_NewExternalTypedDataWithFinalizer(type, data, length, NULL, 0,
                                                NULL);
}

DART_EXPORT Dart_Handle Dart_NewExternalTypedDataWithFinalizer(
    Dart_TypedData_Type type,
    void* data,
    intptr_t length,
    void* peer,
    intptr_t external_allocation_size,
    Dart_WeakPersistentHandleFinalizer callback) {
  DARTSCOPE(Thread::Current());
  if (data == NULL && length != 0) {
    RETURN_NULL_ERROR(data);
  }
  CHECK_CALLBACK_STATE(T);
  switch (type) {
    case Dart_TypedData_kByteData:
      return NewExternalByteData(T, data, length, peer,
                                 external_allocation_size, callback);
    case Dart_TypedData_kInt8:
      return NewExternalTypedData(T, kExternalTypedDataInt8ArrayCid, data,
                                  length, peer, external_allocation_size,
                                  callback);
    case Dart_TypedData_kUint8:
      return NewExternalTypedData(T, kExternalTypedDataUint8ArrayCid, data,
                                  length, peer, external_allocation_size,
                                  callback);
    case Dart_TypedData_kUint8Clamped:
      return NewExternalTypedData(T, kExternalTypedDataUint8ClampedArrayCid,
                                  data, length, peer, external_allocation_size,
                                  callback);
    case Dart_TypedData_kInt16:
      return NewExternalTypedData(T, kExternalTypedDataInt16ArrayCid, data,
                                  length, peer, external_allocation_size,
                                  callback);
    case Dart_TypedData_kUint16:
      return NewExternalTypedData(T, kExternalTypedDataUint16ArrayCid, data,
                                  length, peer, external_allocation_size,
                                  callback);
    case Dart_TypedData_kInt32:
      return NewExternalTypedData(T, kExternalTypedDataInt32ArrayCid, data,
                                  length, peer, external_allocation_size,
                                  callback);
    case Dart_TypedData_kUint32:
      return NewExternalTypedData(T, kExternalTypedDataUint32ArrayCid, data,
                                  length, peer, external_allocation_size,
                                  callback);
    case Dart_TypedData_kInt64:
      return NewExternalTypedData(T, kExternalTypedDataInt64ArrayCid, data,
                                  length, peer, external_allocation_size,
                                  callback);
    case Dart_TypedData_kUint64:
      return NewExternalTypedData(T, kExternalTypedDataUint64ArrayCid, data,
                                  length, peer, external_allocation_size,
                                  callback);
    case Dart_TypedData_kFloat32:
      return NewExternalTypedData(T, kExternalTypedDataFloat32ArrayCid, data,
                                  length, peer, external_allocation_size,
                                  callback);
    case Dart_TypedData_kFloat64:
      return NewExternalTypedData(T, kExternalTypedDataFloat64ArrayCid, data,
                                  length, peer, external_allocation_size,
                                  callback);
    case Dart_TypedData_kFloat32x4:
      return NewExternalTypedData(T, kExternalTypedDataFloat32x4ArrayCid, data,
                                  length, peer, external_allocation_size,
                                  callback);
    default:
      return Api::NewError(
          "%s expects argument 'type' to be of"
          " 'external TypedData'",
          CURRENT_FUNC);
  }
  UNREACHABLE();
  return Api::Null();
}

static ObjectPtr GetByteBufferConstructor(Thread* thread,
                                          const String& class_name,
                                          const String& constructor_name,
                                          intptr_t num_args) {
  const Library& lib =
      Library::Handle(thread->isolate()->object_store()->typed_data_library());
  ASSERT(!lib.IsNull());
  const Class& cls =
      Class::Handle(thread->zone(), lib.LookupClassAllowPrivate(class_name));
  ASSERT(!cls.IsNull());
  return ResolveConstructor(CURRENT_FUNC, cls, class_name, constructor_name,
                            num_args);
}

DART_EXPORT Dart_Handle Dart_NewByteBuffer(Dart_Handle typed_data) {
  DARTSCOPE(Thread::Current());
  intptr_t class_id = Api::ClassId(typed_data);
  if (!IsExternalTypedDataClassId(class_id) &&
      !IsTypedDataViewClassId(class_id) && !IsTypedDataClassId(class_id)) {
    RETURN_TYPE_ERROR(Z, typed_data, 'TypedData');
  }
  Object& result = Object::Handle(Z);
  result = GetByteBufferConstructor(T, Symbols::_ByteBuffer(),
                                    Symbols::_ByteBufferDot_New(), 1);
  ASSERT(!result.IsNull());
  ASSERT(result.IsFunction());
  const Function& factory = Function::Cast(result);
  ASSERT(!factory.IsGenerativeConstructor());

  // Create the argument list.
  const Array& args = Array::Handle(Z, Array::New(2));
  // Factories get type arguments.
  args.SetAt(0, Object::null_type_arguments());
  const Object& obj = Object::Handle(Z, Api::UnwrapHandle(typed_data));
  args.SetAt(1, obj);

  // Invoke the factory constructor and return the new object.
  result = DartEntry::InvokeFunction(factory, args);
  ASSERT(result.IsInstance() || result.IsNull() || result.IsError());
  return Api::NewHandle(T, result.raw());
}

// Structure to record acquired typed data for verification purposes.
class AcquiredData {
 public:
  AcquiredData(void* data, intptr_t size_in_bytes, bool copy)
      : size_in_bytes_(size_in_bytes), data_(data), data_copy_(NULL) {
    if (copy) {
      data_copy_ = malloc(size_in_bytes_);
      memmove(data_copy_, data_, size_in_bytes_);
    }
  }

  // The pointer to hand out via the API.
  void* GetData() const { return data_copy_ != NULL ? data_copy_ : data_; }

  // Writes back and deletes/zaps, if a copy was made.
  ~AcquiredData() {
    if (data_copy_ != NULL) {
      memmove(data_, data_copy_, size_in_bytes_);
      memset(data_copy_, kZapReleasedByte, size_in_bytes_);
      free(data_copy_);
    }
  }

 private:
  static const uint8_t kZapReleasedByte = 0xda;
  intptr_t size_in_bytes_;
  void* data_;
  void* data_copy_;

  DISALLOW_COPY_AND_ASSIGN(AcquiredData);
};

DART_EXPORT Dart_Handle Dart_TypedDataAcquireData(Dart_Handle object,
                                                  Dart_TypedData_Type* type,
                                                  void** data,
                                                  intptr_t* len) {
  DARTSCOPE(Thread::Current());
  Isolate* I = T->isolate();
  intptr_t class_id = Api::ClassId(object);
  if (!IsExternalTypedDataClassId(class_id) &&
      !IsTypedDataViewClassId(class_id) && !IsTypedDataClassId(class_id)) {
    RETURN_TYPE_ERROR(Z, object, 'TypedData');
  }
  if (type == NULL) {
    RETURN_NULL_ERROR(type);
  }
  if (data == NULL) {
    RETURN_NULL_ERROR(data);
  }
  if (len == NULL) {
    RETURN_NULL_ERROR(len);
  }
  // Get the type of typed data object.
  *type = GetType(class_id);
  intptr_t length = 0;
  intptr_t size_in_bytes = 0;
  void* data_tmp = NULL;
  bool external = false;
  T->IncrementNoSafepointScopeDepth();
  START_NO_CALLBACK_SCOPE(T);
  if (IsExternalTypedDataClassId(class_id)) {
    const ExternalTypedData& obj =
        Api::UnwrapExternalTypedDataHandle(Z, object);
    ASSERT(!obj.IsNull());
    length = obj.Length();
    size_in_bytes = length * ExternalTypedData::ElementSizeInBytes(class_id);
    data_tmp = obj.DataAddr(0);
    external = true;
  } else if (IsTypedDataClassId(class_id)) {
    const TypedData& obj = Api::UnwrapTypedDataHandle(Z, object);
    ASSERT(!obj.IsNull());
    length = obj.Length();
    size_in_bytes = length * TypedData::ElementSizeInBytes(class_id);
    data_tmp = obj.DataAddr(0);
  } else {
    ASSERT(IsTypedDataViewClassId(class_id));
    const auto& view_obj = Api::UnwrapTypedDataViewHandle(Z, object);
    ASSERT(!view_obj.IsNull());
    Smi& val = Smi::Handle();
    val = view_obj.length();
    length = val.Value();
    size_in_bytes = length * TypedDataView::ElementSizeInBytes(class_id);
    val = view_obj.offset_in_bytes();
    intptr_t offset_in_bytes = val.Value();
    const auto& obj = Instance::Handle(view_obj.typed_data());
    if (TypedData::IsTypedData(obj)) {
      const TypedData& data_obj = TypedData::Cast(obj);
      data_tmp = data_obj.DataAddr(offset_in_bytes);
    } else {
      ASSERT(ExternalTypedData::IsExternalTypedData(obj));
      const ExternalTypedData& data_obj = ExternalTypedData::Cast(obj);
      data_tmp = data_obj.DataAddr(offset_in_bytes);
      external = true;
    }
  }
  if (FLAG_verify_acquired_data) {
    if (external) {
      ASSERT(!I->heap()->Contains(reinterpret_cast<uword>(data_tmp)));
    } else {
      ASSERT(I->heap()->Contains(reinterpret_cast<uword>(data_tmp)));
    }
    const Object& obj = Object::Handle(Z, Api::UnwrapHandle(object));
    WeakTable* table = I->group()->api_state()->acquired_table();
    intptr_t current = table->GetValue(obj.raw());
    if (current != 0) {
      return Api::NewError("Data was already acquired for this object.");
    }
    // Do not make a copy if the data is external. Some callers expect external
    // data to remain in place, even though the API spec doesn't guarantee it.
    // TODO(koda/asiva): Make final decision and document it.
    AcquiredData* ad = new AcquiredData(data_tmp, size_in_bytes, !external);
    table->SetValue(obj.raw(), reinterpret_cast<intptr_t>(ad));
    data_tmp = ad->GetData();
  }
  *data = data_tmp;
  *len = length;
  return Api::Success();
}

DART_EXPORT Dart_Handle Dart_TypedDataReleaseData(Dart_Handle object) {
  DARTSCOPE(Thread::Current());
  Isolate* I = T->isolate();
  intptr_t class_id = Api::ClassId(object);
  if (!IsExternalTypedDataClassId(class_id) &&
      !IsTypedDataViewClassId(class_id) && !IsTypedDataClassId(class_id)) {
    RETURN_TYPE_ERROR(Z, object, 'TypedData');
  }
  T->DecrementNoSafepointScopeDepth();
  END_NO_CALLBACK_SCOPE(T);
  if (FLAG_verify_acquired_data) {
    const Object& obj = Object::Handle(Z, Api::UnwrapHandle(object));
    WeakTable* table = I->group()->api_state()->acquired_table();
    intptr_t current = table->GetValue(obj.raw());
    if (current == 0) {
      return Api::NewError("Data was not acquired for this object.");
    }
    AcquiredData* ad = reinterpret_cast<AcquiredData*>(current);
    table->SetValue(obj.raw(), 0);  // Delete entry from table.
    delete ad;
  }
  return Api::Success();
}

DART_EXPORT Dart_Handle Dart_GetDataFromByteBuffer(Dart_Handle object) {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  Isolate* isolate = thread->isolate();
  CHECK_ISOLATE(isolate);
  TransitionNativeToVM transition(thread);
  intptr_t class_id = Api::ClassId(object);
  if (class_id != kByteBufferCid) {
    RETURN_TYPE_ERROR(zone, object, 'ByteBuffer');
  }
  const Instance& instance = Api::UnwrapInstanceHandle(zone, object);
  ASSERT(!instance.IsNull());
  return Api::NewHandle(thread, ByteBuffer::Data(instance));
}

// ---  Invoking Constructors, Methods, and Field accessors ---

static ObjectPtr ResolveConstructor(const char* current_func,
                                    const Class& cls,
                                    const String& class_name,
                                    const String& constr_name,
                                    int num_args) {
  // The constructor must be present in the interface.
  const Function& constructor =
      Function::Handle(cls.LookupFunctionAllowPrivate(constr_name));
  if (constructor.IsNull() ||
      (!constructor.IsGenerativeConstructor() && !constructor.IsFactory())) {
    const String& lookup_class_name = String::Handle(cls.Name());
    if (!class_name.Equals(lookup_class_name)) {
      // When the class name used to build the constructor name is
      // different than the name of the class in which we are doing
      // the lookup, it can be confusing to the user to figure out
      // what's going on.  Be a little more explicit for these error
      // messages.
      const String& message = String::Handle(String::NewFormatted(
          "%s: could not find factory '%s' in class '%s'.", current_func,
          constr_name.ToCString(), lookup_class_name.ToCString()));
      return ApiError::New(message);
    } else {
      const String& message = String::Handle(
          String::NewFormatted("%s: could not find constructor '%s'.",
                               current_func, constr_name.ToCString()));
      return ApiError::New(message);
    }
  }
  const int kTypeArgsLen = 0;
  const int extra_args = 1;
  String& error_message = String::Handle();
  if (!constructor.AreValidArgumentCounts(kTypeArgsLen, num_args + extra_args,
                                          0, &error_message)) {
    const String& message = String::Handle(String::NewFormatted(
        "%s: wrong argument count for "
        "constructor '%s': %s.",
        current_func, constr_name.ToCString(), error_message.ToCString()));
    return ApiError::New(message);
  }
  ErrorPtr error = constructor.VerifyCallEntryPoint();
  if (error != Error::null()) return error;
  return constructor.raw();
}

DART_EXPORT Dart_Handle Dart_New(Dart_Handle type,
                                 Dart_Handle constructor_name,
                                 int number_of_arguments,
                                 Dart_Handle* arguments) {
  DARTSCOPE(Thread::Current());
  CHECK_CALLBACK_STATE(T);
  Object& result = Object::Handle(Z);

  if (number_of_arguments < 0) {
    return Api::NewError(
        "%s expects argument 'number_of_arguments' to be non-negative.",
        CURRENT_FUNC);
  }

  // Get the class to instantiate.
  Object& unchecked_type = Object::Handle(Api::UnwrapHandle(type));
  if (unchecked_type.IsNull() || !unchecked_type.IsType()) {
    RETURN_TYPE_ERROR(Z, type, Type);
  }
  Type& type_obj = Type::Handle();
  type_obj ^= unchecked_type.raw();
  if (!type_obj.IsFinalized()) {
    return Api::NewError(
        "%s expects argument 'type' to be a fully resolved type.",
        CURRENT_FUNC);
  }
  Class& cls = Class::Handle(Z, type_obj.type_class());
  TypeArguments& type_arguments =
      TypeArguments::Handle(Z, type_obj.arguments());

  const String& base_constructor_name = String::Handle(Z, cls.Name());

  // And get the name of the constructor to invoke.
  String& dot_name = String::Handle(Z);
  result = Api::UnwrapHandle(constructor_name);
  if (result.IsNull()) {
    dot_name = Symbols::Dot().raw();
  } else if (result.IsString()) {
    dot_name = String::Concat(Symbols::Dot(), String::Cast(result));
  } else {
    RETURN_TYPE_ERROR(Z, constructor_name, String);
  }

  // Resolve the constructor.
  String& constr_name =
      String::Handle(String::Concat(base_constructor_name, dot_name));
  result = ResolveConstructor("Dart_New", cls, base_constructor_name,
                              constr_name, number_of_arguments);
  if (result.IsError()) {
    return Api::NewHandle(T, result.raw());
  }
  ASSERT(result.IsFunction());
  Function& constructor = Function::Handle(Z);
  constructor ^= result.raw();

  Instance& new_object = Instance::Handle(Z);
  if (constructor.IsRedirectingFactory()) {
    Type& redirect_type = Type::Handle(constructor.RedirectionType());
    constructor = constructor.RedirectionTarget();
    ASSERT(!constructor.IsNull());

    if (!redirect_type.IsInstantiated()) {
      // The type arguments of the redirection type are instantiated from the
      // type arguments of the type argument.
      // We do not support generic constructors.
      ASSERT(redirect_type.IsInstantiated(kFunctions));
      redirect_type ^= redirect_type.InstantiateFrom(
          type_arguments, Object::null_type_arguments(), kNoneFree, NULL,
          Heap::kNew);
      redirect_type ^= redirect_type.Canonicalize();
    }

    type_obj = redirect_type.raw();
    type_arguments = redirect_type.arguments();

    cls = type_obj.type_class();
  }
  if (constructor.IsGenerativeConstructor()) {
    CHECK_ERROR_HANDLE(cls.VerifyEntryPoint());
#if defined(DEBUG)
    if (!cls.is_allocated() &&
        (Dart::vm_snapshot_kind() == Snapshot::kFullAOT)) {
      return Api::NewError("Precompilation dropped '%s'", cls.ToCString());
    }
#endif
    // Create the new object.
    new_object = Instance::New(cls);
  }

  // Create the argument list.
  intptr_t arg_index = 0;
  int extra_args = 1;
  const Array& args =
      Array::Handle(Z, Array::New(number_of_arguments + extra_args));
  if (constructor.IsGenerativeConstructor()) {
    // Constructors get the uninitialized object.
    if (!type_arguments.IsNull()) {
      // The type arguments will be null if the class has no type parameters, in
      // which case the following call would fail because there is no slot
      // reserved in the object for the type vector.
      new_object.SetTypeArguments(type_arguments);
    }
    args.SetAt(arg_index++, new_object);
  } else {
    // Factories get type arguments.
    args.SetAt(arg_index++, type_arguments);
  }
  Object& argument = Object::Handle(Z);
  for (int i = 0; i < number_of_arguments; i++) {
    argument = Api::UnwrapHandle(arguments[i]);
    if (!argument.IsNull() && !argument.IsInstance()) {
      if (argument.IsError()) {
        return Api::NewHandle(T, argument.raw());
      } else {
        return Api::NewError(
            "%s expects arguments[%d] to be an Instance handle.", CURRENT_FUNC,
            i);
      }
    }
    args.SetAt(arg_index++, argument);
  }

  // Invoke the constructor and return the new object.
  result = DartEntry::InvokeFunction(constructor, args);
  if (result.IsError()) {
    return Api::NewHandle(T, result.raw());
  }

  if (constructor.IsGenerativeConstructor()) {
    ASSERT(result.IsNull());
  } else {
    ASSERT(result.IsNull() || result.IsInstance());
    new_object ^= result.raw();
  }
  return Api::NewHandle(T, new_object.raw());
}

static InstancePtr AllocateObject(Thread* thread, const Class& cls) {
  if (!cls.is_fields_marked_nullable()) {
    // Mark all fields as nullable.
    Zone* zone = thread->zone();
    Class& iterate_cls = Class::Handle(zone, cls.raw());
    Field& field = Field::Handle(zone);
    Array& fields = Array::Handle(zone);
    while (!iterate_cls.IsNull()) {
      ASSERT(iterate_cls.is_finalized());
      iterate_cls.set_is_fields_marked_nullable();
      fields = iterate_cls.fields();
      iterate_cls = iterate_cls.SuperClass();
      for (int field_num = 0; field_num < fields.Length(); field_num++) {
        field ^= fields.At(field_num);
        if (field.is_static()) {
          continue;
        }
        field.RecordStore(Object::null_object());
      }
    }
  }

  // Allocate an object for the given class.
  return Instance::New(cls);
}

DART_EXPORT Dart_Handle Dart_Allocate(Dart_Handle type) {
  DARTSCOPE(Thread::Current());
  CHECK_CALLBACK_STATE(T);

  const Type& type_obj = Api::UnwrapTypeHandle(Z, type);
  // Get the class to instantiate.
  if (type_obj.IsNull()) {
    RETURN_TYPE_ERROR(Z, type, Type);
  }
  const Class& cls = Class::Handle(Z, type_obj.type_class());
  CHECK_ERROR_HANDLE(cls.VerifyEntryPoint());
#if defined(DEBUG)
  if (!cls.is_allocated() && (Dart::vm_snapshot_kind() == Snapshot::kFullAOT)) {
    return Api::NewError("Precompilation dropped '%s'", cls.ToCString());
  }
#endif
  CHECK_ERROR_HANDLE(cls.EnsureIsFinalized(T));
  return Api::NewHandle(T, AllocateObject(T, cls));
}

DART_EXPORT Dart_Handle
Dart_AllocateWithNativeFields(Dart_Handle type,
                              intptr_t num_native_fields,
                              const intptr_t* native_fields) {
  DARTSCOPE(Thread::Current());
  CHECK_CALLBACK_STATE(T);

  const Type& type_obj = Api::UnwrapTypeHandle(Z, type);
  // Get the class to instantiate.
  if (type_obj.IsNull()) {
    RETURN_TYPE_ERROR(Z, type, Type);
  }
  if (native_fields == NULL) {
    RETURN_NULL_ERROR(native_fields);
  }
  const Class& cls = Class::Handle(Z, type_obj.type_class());
  CHECK_ERROR_HANDLE(cls.VerifyEntryPoint());
#if defined(DEBUG)
  if (!cls.is_allocated() && (Dart::vm_snapshot_kind() == Snapshot::kFullAOT)) {
    return Api::NewError("Precompilation dropped '%s'", cls.ToCString());
  }
#endif
  CHECK_ERROR_HANDLE(cls.EnsureIsFinalized(T));
  if (num_native_fields != cls.num_native_fields()) {
    return Api::NewError(
        "%s: invalid number of native fields %" Pd " passed in, expected %d",
        CURRENT_FUNC, num_native_fields, cls.num_native_fields());
  }
  const Instance& instance = Instance::Handle(Z, AllocateObject(T, cls));
  instance.SetNativeFields(num_native_fields, native_fields);
  return Api::NewHandle(T, instance.raw());
}

static Dart_Handle SetupArguments(Thread* thread,
                                  int num_args,
                                  Dart_Handle* arguments,
                                  int extra_args,
                                  Array* args) {
  Zone* zone = thread->zone();
  // Check for malformed arguments in the arguments list.
  *args = Array::New(num_args + extra_args);
  Object& arg = Object::Handle(zone);
  for (int i = 0; i < num_args; i++) {
    arg = Api::UnwrapHandle(arguments[i]);
    if (!arg.IsNull() && !arg.IsInstance()) {
      *args = Array::null();
      if (arg.IsError()) {
        return Api::NewHandle(thread, arg.raw());
      } else {
        return Api::NewError(
            "%s expects arguments[%d] to be an Instance handle.", "Dart_Invoke",
            i);
      }
    }
    args->SetAt((i + extra_args), arg);
  }
  return Api::Success();
}

DART_EXPORT Dart_Handle Dart_InvokeConstructor(Dart_Handle object,
                                               Dart_Handle name,
                                               int number_of_arguments,
                                               Dart_Handle* arguments) {
  DARTSCOPE(Thread::Current());
  API_TIMELINE_DURATION(T);
  CHECK_CALLBACK_STATE(T);

  if (number_of_arguments < 0) {
    return Api::NewError(
        "%s expects argument 'number_of_arguments' to be non-negative.",
        CURRENT_FUNC);
  }
  const Instance& instance = Api::UnwrapInstanceHandle(Z, object);
  if (instance.IsNull()) {
    RETURN_TYPE_ERROR(Z, object, Instance);
  }

  // Since we have allocated an object it would mean that the type
  // is finalized.
  // TODO(asiva): How do we ensure that a constructor is not called more than
  // once for the same object.

  // Construct name of the constructor to invoke.
  const String& constructor_name = Api::UnwrapStringHandle(Z, name);
  const AbstractType& type_obj =
      AbstractType::Handle(Z, instance.GetType(Heap::kNew));
  const Class& cls = Class::Handle(Z, type_obj.type_class());
  const String& class_name = String::Handle(Z, cls.Name());
  const Array& strings = Array::Handle(Z, Array::New(3));
  strings.SetAt(0, class_name);
  strings.SetAt(1, Symbols::Dot());
  if (constructor_name.IsNull()) {
    strings.SetAt(2, Symbols::Empty());
  } else {
    strings.SetAt(2, constructor_name);
  }
  const String& dot_name = String::Handle(Z, String::ConcatAll(strings));
  const TypeArguments& type_arguments =
      TypeArguments::Handle(Z, type_obj.arguments());
  const Function& constructor =
      Function::Handle(Z, cls.LookupFunctionAllowPrivate(dot_name));
  const int kTypeArgsLen = 0;
  const int extra_args = 1;
  if (!constructor.IsNull() && constructor.IsGenerativeConstructor() &&
      constructor.AreValidArgumentCounts(
          kTypeArgsLen, number_of_arguments + extra_args, 0, NULL)) {
    CHECK_ERROR_HANDLE(constructor.VerifyCallEntryPoint());
    // Create the argument list.
    // Constructors get the uninitialized object.
    if (!type_arguments.IsNull()) {
      // The type arguments will be null if the class has no type
      // parameters, in which case the following call would fail
      // because there is no slot reserved in the object for the
      // type vector.
      instance.SetTypeArguments(type_arguments);
    }
    Dart_Handle result;
    Array& args = Array::Handle(Z);
    result =
        SetupArguments(T, number_of_arguments, arguments, extra_args, &args);
    if (!Api::IsError(result)) {
      args.SetAt(0, instance);
      const Object& retval =
          Object::Handle(Z, DartEntry::InvokeFunction(constructor, args));
      if (retval.IsError()) {
        result = Api::NewHandle(T, retval.raw());
      } else {
        result = Api::NewHandle(T, instance.raw());
      }
    }
    return result;
  }
  return Api::NewError("%s expects argument 'name' to be a valid constructor.",
                       CURRENT_FUNC);
}

DART_EXPORT Dart_Handle Dart_Invoke(Dart_Handle target,
                                    Dart_Handle name,
                                    int number_of_arguments,
                                    Dart_Handle* arguments) {
  DARTSCOPE(Thread::Current());
  API_TIMELINE_DURATION(T);
  CHECK_CALLBACK_STATE(T);

  String& function_name =
      String::Handle(Z, Api::UnwrapStringHandle(Z, name).raw());
  if (function_name.IsNull()) {
    RETURN_TYPE_ERROR(Z, name, String);
  }
  if (number_of_arguments < 0) {
    return Api::NewError(
        "%s expects argument 'number_of_arguments' to be non-negative.",
        CURRENT_FUNC);
  }
  const Object& obj = Object::Handle(Z, Api::UnwrapHandle(target));
  if (obj.IsError()) {
    return target;
  }
  Dart_Handle result;
  Array& args = Array::Handle(Z);
  // This API does not provide a way to pass named parameters.
  const Array& arg_names = Object::empty_array();
  const bool respect_reflectable = false;
  const bool check_is_entrypoint = FLAG_verify_entry_points;
  if (obj.IsType()) {
    if (!Type::Cast(obj).IsFinalized()) {
      return Api::NewError(
          "%s expects argument 'target' to be a fully resolved type.",
          CURRENT_FUNC);
    }

    const Class& cls = Class::Handle(Z, Type::Cast(obj).type_class());
    if (Library::IsPrivate(function_name)) {
      const Library& lib = Library::Handle(Z, cls.library());
      function_name = lib.PrivateName(function_name);
    }

    // Setup args and check for malformed arguments in the arguments list.
    result = SetupArguments(T, number_of_arguments, arguments, 0, &args);
    if (Api::IsError(result)) {
      return result;
    }
    return Api::NewHandle(
        T, cls.Invoke(function_name, args, arg_names, respect_reflectable,
                      check_is_entrypoint));
  } else if (obj.IsNull() || obj.IsInstance()) {
    // Since we have allocated an object it would mean that the type of the
    // receiver is already resolved and finalized, hence it is not necessary
    // to check here.
    Instance& instance = Instance::Handle(Z);
    instance ^= obj.raw();

    // Setup args and check for malformed arguments in the arguments list.
    result = SetupArguments(T, number_of_arguments, arguments, 1, &args);
    if (Api::IsError(result)) {
      return result;
    }
    args.SetAt(0, instance);
    return Api::NewHandle(
        T, instance.Invoke(function_name, args, arg_names, respect_reflectable,
                           check_is_entrypoint));
  } else if (obj.IsLibrary()) {
    // Check whether class finalization is needed.
    const Library& lib = Library::Cast(obj);

    // Check that the library is loaded.
    if (!lib.Loaded()) {
      return Api::NewError("%s expects library argument 'target' to be loaded.",
                           CURRENT_FUNC);
    }

    if (Library::IsPrivate(function_name)) {
      function_name = lib.PrivateName(function_name);
    }

    // Setup args and check for malformed arguments in the arguments list.
    result = SetupArguments(T, number_of_arguments, arguments, 0, &args);
    if (Api::IsError(result)) {
      return result;
    }

    return Api::NewHandle(
        T, lib.Invoke(function_name, args, arg_names, respect_reflectable,
                      check_is_entrypoint));
  } else {
    return Api::NewError(
        "%s expects argument 'target' to be an object, type, or library.",
        CURRENT_FUNC);
  }
}

DART_EXPORT Dart_Handle Dart_InvokeClosure(Dart_Handle closure,
                                           int number_of_arguments,
                                           Dart_Handle* arguments) {
  DARTSCOPE(Thread::Current());
  API_TIMELINE_DURATION(T);
  CHECK_CALLBACK_STATE(T);
  const Instance& closure_obj = Api::UnwrapInstanceHandle(Z, closure);
  if (closure_obj.IsNull() || !closure_obj.IsCallable(NULL)) {
    RETURN_TYPE_ERROR(Z, closure, Instance);
  }
  if (number_of_arguments < 0) {
    return Api::NewError(
        "%s expects argument 'number_of_arguments' to be non-negative.",
        CURRENT_FUNC);
  }

  // Set up arguments to include the closure as the first argument.
  const Array& args = Array::Handle(Z, Array::New(number_of_arguments + 1));
  Object& obj = Object::Handle(Z);
  args.SetAt(0, closure_obj);
  for (int i = 0; i < number_of_arguments; i++) {
    obj = Api::UnwrapHandle(arguments[i]);
    if (!obj.IsNull() && !obj.IsInstance()) {
      RETURN_TYPE_ERROR(Z, arguments[i], Instance);
    }
    args.SetAt(i + 1, obj);
  }
  // Now try to invoke the closure.
  return Api::NewHandle(T, DartEntry::InvokeClosure(args));
}

DART_EXPORT Dart_Handle Dart_GetField(Dart_Handle container, Dart_Handle name) {
  DARTSCOPE(Thread::Current());
  API_TIMELINE_DURATION(T);
  CHECK_CALLBACK_STATE(T);

  String& field_name =
      String::Handle(Z, Api::UnwrapStringHandle(Z, name).raw());
  if (field_name.IsNull()) {
    RETURN_TYPE_ERROR(Z, name, String);
  }
  const Object& obj = Object::Handle(Z, Api::UnwrapHandle(container));
  const bool throw_nsm_if_absent = true;
  const bool respect_reflectable = false;
  const bool check_is_entrypoint = FLAG_verify_entry_points;

  if (obj.IsType()) {
    if (!Type::Cast(obj).IsFinalized()) {
      return Api::NewError(
          "%s expects argument 'container' to be a fully resolved type.",
          CURRENT_FUNC);
    }
    Class& cls = Class::Handle(Z, Type::Cast(obj).type_class());
    if (Library::IsPrivate(field_name)) {
      const Library& lib = Library::Handle(Z, cls.library());
      field_name = lib.PrivateName(field_name);
    }
    return Api::NewHandle(
        T, cls.InvokeGetter(field_name, throw_nsm_if_absent,
                            respect_reflectable, check_is_entrypoint));
  } else if (obj.IsNull() || obj.IsInstance()) {
    Instance& instance = Instance::Handle(Z);
    instance ^= obj.raw();
    if (Library::IsPrivate(field_name)) {
      const Class& cls = Class::Handle(Z, instance.clazz());
      const Library& lib = Library::Handle(Z, cls.library());
      field_name = lib.PrivateName(field_name);
    }
    return Api::NewHandle(T,
                          instance.InvokeGetter(field_name, respect_reflectable,
                                                check_is_entrypoint));
  } else if (obj.IsLibrary()) {
    const Library& lib = Library::Cast(obj);
    // Check that the library is loaded.
    if (!lib.Loaded()) {
      return Api::NewError(
          "%s expects library argument 'container' to be loaded.",
          CURRENT_FUNC);
    }
    if (Library::IsPrivate(field_name)) {
      field_name = lib.PrivateName(field_name);
    }
    return Api::NewHandle(
        T, lib.InvokeGetter(field_name, throw_nsm_if_absent,
                            respect_reflectable, check_is_entrypoint));
  } else if (obj.IsError()) {
    return container;
  } else {
    return Api::NewError(
        "%s expects argument 'container' to be an object, type, or library.",
        CURRENT_FUNC);
  }
}

DART_EXPORT Dart_Handle Dart_SetField(Dart_Handle container,
                                      Dart_Handle name,
                                      Dart_Handle value) {
  DARTSCOPE(Thread::Current());
  API_TIMELINE_DURATION(T);
  CHECK_CALLBACK_STATE(T);

  String& field_name =
      String::Handle(Z, Api::UnwrapStringHandle(Z, name).raw());
  if (field_name.IsNull()) {
    RETURN_TYPE_ERROR(Z, name, String);
  }

  // Since null is allowed for value, we don't use UnwrapInstanceHandle.
  const Object& value_obj = Object::Handle(Z, Api::UnwrapHandle(value));
  if (!value_obj.IsNull() && !value_obj.IsInstance()) {
    RETURN_TYPE_ERROR(Z, value, Instance);
  }
  Instance& value_instance = Instance::Handle(Z);
  value_instance ^= value_obj.raw();

  const Object& obj = Object::Handle(Z, Api::UnwrapHandle(container));
  const bool respect_reflectable = false;
  const bool check_is_entrypoint = FLAG_verify_entry_points;

  if (obj.IsType()) {
    if (!Type::Cast(obj).IsFinalized()) {
      return Api::NewError(
          "%s expects argument 'container' to be a fully resolved type.",
          CURRENT_FUNC);
    }

    // To access a static field we may need to use the Field or the
    // setter Function.
    Class& cls = Class::Handle(Z, Type::Cast(obj).type_class());
    if (Library::IsPrivate(field_name)) {
      const Library& lib = Library::Handle(Z, cls.library());
      field_name = lib.PrivateName(field_name);
    }
    return Api::NewHandle(
        T, cls.InvokeSetter(field_name, value_instance, respect_reflectable,
                            check_is_entrypoint));
  } else if (obj.IsNull() || obj.IsInstance()) {
    Instance& instance = Instance::Handle(Z);
    instance ^= obj.raw();
    if (Library::IsPrivate(field_name)) {
      const Class& cls = Class::Handle(Z, instance.clazz());
      const Library& lib = Library::Handle(Z, cls.library());
      field_name = lib.PrivateName(field_name);
    }
    return Api::NewHandle(
        T, instance.InvokeSetter(field_name, value_instance,
                                 respect_reflectable, check_is_entrypoint));
  } else if (obj.IsLibrary()) {
    // To access a top-level we may need to use the Field or the
    // setter Function.  The setter function may either be in the
    // library or in the field's owner class, depending.
    const Library& lib = Library::Cast(obj);
    // Check that the library is loaded.
    if (!lib.Loaded()) {
      return Api::NewError(
          "%s expects library argument 'container' to be loaded.",
          CURRENT_FUNC);
    }

    if (Library::IsPrivate(field_name)) {
      field_name = lib.PrivateName(field_name);
    }
    return Api::NewHandle(
        T, lib.InvokeSetter(field_name, value_instance, respect_reflectable,
                            check_is_entrypoint));
  } else if (obj.IsError()) {
    return container;
  }
  return Api::NewError(
      "%s expects argument 'container' to be an object, type, or library.",
      CURRENT_FUNC);
}

// --- Exceptions ----

DART_EXPORT Dart_Handle Dart_ThrowException(Dart_Handle exception) {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  Isolate* isolate = thread->isolate();
  CHECK_ISOLATE(isolate);
  CHECK_CALLBACK_STATE(thread);
  if (::Dart_IsError(exception)) {
    ::Dart_PropagateError(exception);
  }
  TransitionNativeToVM transition(thread);
  const Instance& excp = Api::UnwrapInstanceHandle(zone, exception);
  if (excp.IsNull()) {
    RETURN_TYPE_ERROR(zone, exception, Instance);
  }
  if (thread->top_exit_frame_info() == 0) {
    // There are no dart frames on the stack so it would be illegal to
    // throw an exception here.
    return Api::NewError("No Dart frames on stack, cannot throw exception");
  }
  // Unwind all the API scopes till the exit frame before throwing an
  // exception.
  const Instance* saved_exception;
  {
    NoSafepointScope no_safepoint;
    InstancePtr raw_exception =
        Api::UnwrapInstanceHandle(zone, exception).raw();
    thread->UnwindScopes(thread->top_exit_frame_info());
    saved_exception = &Instance::Handle(raw_exception);
  }
  Exceptions::Throw(thread, *saved_exception);
  return Api::NewError("Exception was not thrown, internal error");
}

DART_EXPORT Dart_Handle Dart_ReThrowException(Dart_Handle exception,
                                              Dart_Handle stacktrace) {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  Isolate* isolate = thread->isolate();
  CHECK_ISOLATE(isolate);
  CHECK_CALLBACK_STATE(thread);
  TransitionNativeToVM transition(thread);
  {
    const Instance& excp = Api::UnwrapInstanceHandle(zone, exception);
    if (excp.IsNull()) {
      RETURN_TYPE_ERROR(zone, exception, Instance);
    }
    const Instance& stk = Api::UnwrapInstanceHandle(zone, stacktrace);
    if (stk.IsNull()) {
      RETURN_TYPE_ERROR(zone, stacktrace, Instance);
    }
  }
  if (thread->top_exit_frame_info() == 0) {
    // There are no dart frames on the stack so it would be illegal to
    // throw an exception here.
    return Api::NewError("No Dart frames on stack, cannot throw exception");
  }
  // Unwind all the API scopes till the exit frame before throwing an
  // exception.
  const Instance* saved_exception;
  const StackTrace* saved_stacktrace;
  {
    NoSafepointScope no_safepoint;
    InstancePtr raw_exception =
        Api::UnwrapInstanceHandle(zone, exception).raw();
    StackTracePtr raw_stacktrace =
        Api::UnwrapStackTraceHandle(zone, stacktrace).raw();
    thread->UnwindScopes(thread->top_exit_frame_info());
    saved_exception = &Instance::Handle(raw_exception);
    saved_stacktrace = &StackTrace::Handle(raw_stacktrace);
  }
  Exceptions::ReThrow(thread, *saved_exception, *saved_stacktrace);
  return Api::NewError("Exception was not re thrown, internal error");
}

// --- Native fields and functions ---

DART_EXPORT Dart_Handle Dart_GetNativeInstanceFieldCount(Dart_Handle obj,
                                                         int* count) {
  Thread* thread = Thread::Current();
  CHECK_ISOLATE(thread->isolate());
  TransitionNativeToVM transition(thread);
  ReusableObjectHandleScope reused_obj_handle(thread);
  const Instance& instance = Api::UnwrapInstanceHandle(reused_obj_handle, obj);
  if (instance.IsNull()) {
    RETURN_TYPE_ERROR(thread->zone(), obj, Instance);
  }
  *count = instance.NumNativeFields();
  return Api::Success();
}

DART_EXPORT Dart_Handle Dart_GetNativeInstanceField(Dart_Handle obj,
                                                    int index,
                                                    intptr_t* value) {
  Thread* thread = Thread::Current();
  CHECK_ISOLATE(thread->isolate());
  TransitionNativeToVM transition(thread);
  ReusableObjectHandleScope reused_obj_handle(thread);
  const Instance& instance = Api::UnwrapInstanceHandle(reused_obj_handle, obj);
  if (instance.IsNull()) {
    RETURN_TYPE_ERROR(thread->zone(), obj, Instance);
  }
  if (!instance.IsValidNativeIndex(index)) {
    return Api::NewError(
        "%s: invalid index %d passed in to access native instance field",
        CURRENT_FUNC, index);
  }
  *value = instance.GetNativeField(index);
  return Api::Success();
}

DART_EXPORT Dart_Handle Dart_SetNativeInstanceField(Dart_Handle obj,
                                                    int index,
                                                    intptr_t value) {
  DARTSCOPE(Thread::Current());
  const Instance& instance = Api::UnwrapInstanceHandle(Z, obj);
  if (instance.IsNull()) {
    RETURN_TYPE_ERROR(Z, obj, Instance);
  }
  if (!instance.IsValidNativeIndex(index)) {
    return Api::NewError(
        "%s: invalid index %d passed in to set native instance field",
        CURRENT_FUNC, index);
  }
  instance.SetNativeField(index, value);
  return Api::Success();
}

DART_EXPORT void* Dart_GetNativeIsolateGroupData(Dart_NativeArguments args) {
  NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
  Isolate* isolate = arguments->thread()->isolate();
  ASSERT(isolate == Isolate::Current());
  return isolate->init_callback_data();
}

DART_EXPORT Dart_Handle Dart_GetNativeArguments(
    Dart_NativeArguments args,
    int num_arguments,
    const Dart_NativeArgument_Descriptor* argument_descriptors,
    Dart_NativeArgument_Value* arg_values) {
  NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
  TransitionNativeToVM transition(arguments->thread());
  ASSERT(arguments->thread()->isolate() == Isolate::Current());
  if (arg_values == NULL) {
    RETURN_NULL_ERROR(arg_values);
  }
  for (int i = 0; i < num_arguments; i++) {
    Dart_NativeArgument_Descriptor desc = argument_descriptors[i];
    Dart_NativeArgument_Type arg_type =
        static_cast<Dart_NativeArgument_Type>(desc.type);
    int arg_index = desc.index;
    ASSERT(arg_index >= 0 && arg_index < arguments->NativeArgCount());
    Dart_NativeArgument_Value* native_value = &(arg_values[i]);
    switch (arg_type) {
      case Dart_NativeArgument_kBool:
        if (!Api::GetNativeBooleanArgument(arguments, arg_index,
                                           &(native_value->as_bool))) {
          return Api::NewArgumentError(
              "%s: expects argument at index %d to be of"
              " type Boolean.",
              CURRENT_FUNC, i);
        }
        break;

      case Dart_NativeArgument_kInt32: {
        int64_t value = 0;
        if (!GetNativeIntegerArgument(arguments, arg_index, &value)) {
          return Api::NewArgumentError(
              "%s: expects argument at index %d to be of"
              " type Integer.",
              CURRENT_FUNC, i);
        }
        if (value < INT32_MIN || value > INT32_MAX) {
          return Api::NewArgumentError(
              "%s: argument value at index %d is out of range", CURRENT_FUNC,
              i);
        }
        native_value->as_int32 = static_cast<int32_t>(value);
        break;
      }

      case Dart_NativeArgument_kUint32: {
        int64_t value = 0;
        if (!GetNativeIntegerArgument(arguments, arg_index, &value)) {
          return Api::NewArgumentError(
              "%s: expects argument at index %d to be of"
              " type Integer.",
              CURRENT_FUNC, i);
        }
        if (value < 0 || value > UINT32_MAX) {
          return Api::NewArgumentError(
              "%s: argument value at index %d is out of range", CURRENT_FUNC,
              i);
        }
        native_value->as_uint32 = static_cast<uint32_t>(value);
        break;
      }

      case Dart_NativeArgument_kInt64: {
        int64_t value = 0;
        if (!GetNativeIntegerArgument(arguments, arg_index, &value)) {
          return Api::NewArgumentError(
              "%s: expects argument at index %d to be of"
              " type Integer.",
              CURRENT_FUNC, i);
        }
        native_value->as_int64 = value;
        break;
      }

      case Dart_NativeArgument_kUint64: {
        uint64_t value = 0;
        if (!GetNativeUnsignedIntegerArgument(arguments, arg_index, &value)) {
          return Api::NewArgumentError(
              "%s: expects argument at index %d to be of"
              " type Integer.",
              CURRENT_FUNC, i);
        }
        native_value->as_uint64 = value;
        break;
      }

      case Dart_NativeArgument_kDouble:
        if (!GetNativeDoubleArgument(arguments, arg_index,
                                     &(native_value->as_double))) {
          return Api::NewArgumentError(
              "%s: expects argument at index %d to be of"
              " type Double.",
              CURRENT_FUNC, i);
        }
        break;

      case Dart_NativeArgument_kString:
        if (!GetNativeStringArgument(arguments, arg_index,
                                     &(native_value->as_string.dart_str),
                                     &(native_value->as_string.peer))) {
          return Api::NewArgumentError(
              "%s: expects argument at index %d to be of"
              " type String.",
              CURRENT_FUNC, i);
        }
        break;

      case Dart_NativeArgument_kNativeFields: {
        Dart_Handle result = GetNativeFieldsOfArgument(
            arguments, arg_index, native_value->as_native_fields.num_fields,
            native_value->as_native_fields.values, CURRENT_FUNC);
        if (result != Api::Success()) {
          return result;
        }
        break;
      }

      case Dart_NativeArgument_kInstance: {
        ASSERT(arguments->thread() == Thread::Current());
        ASSERT(arguments->thread()->api_top_scope() != NULL);
        native_value->as_instance = Api::NewHandle(
            arguments->thread(), arguments->NativeArgAt(arg_index));
        break;
      }

      default:
        return Api::NewArgumentError("%s: invalid argument type %d.",
                                     CURRENT_FUNC, arg_type);
    }
  }
  return Api::Success();
}

DART_EXPORT Dart_Handle Dart_GetNativeArgument(Dart_NativeArguments args,
                                               int index) {
  NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
  if ((index < 0) || (index >= arguments->NativeArgCount())) {
    return Api::NewError(
        "%s: argument 'index' out of range. Expected 0..%d but saw %d.",
        CURRENT_FUNC, arguments->NativeArgCount() - 1, index);
  }
  TransitionNativeToVM transition(arguments->thread());
  return Api::NewHandle(arguments->thread(), arguments->NativeArgAt(index));
}

DART_EXPORT int Dart_GetNativeArgumentCount(Dart_NativeArguments args) {
  NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
  return arguments->NativeArgCount();
}

DART_EXPORT Dart_Handle
Dart_GetNativeFieldsOfArgument(Dart_NativeArguments args,
                               int arg_index,
                               int num_fields,
                               intptr_t* field_values) {
  NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
  if ((arg_index < 0) || (arg_index >= arguments->NativeArgCount())) {
    return Api::NewError(
        "%s: argument 'arg_index' out of range. Expected 0..%d but saw %d.",
        CURRENT_FUNC, arguments->NativeArgCount() - 1, arg_index);
  }
  if (field_values == NULL) {
    RETURN_NULL_ERROR(field_values);
  }
  return GetNativeFieldsOfArgument(arguments, arg_index, num_fields,
                                   field_values, CURRENT_FUNC);
}

DART_EXPORT Dart_Handle Dart_GetNativeReceiver(Dart_NativeArguments args,
                                               intptr_t* value) {
  NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
  TransitionNativeToVM transition(arguments->thread());
  ASSERT(arguments->thread()->isolate() == Isolate::Current());
  if (value == NULL) {
    RETURN_NULL_ERROR(value);
  }
  if (Api::GetNativeReceiver(arguments, value)) {
    return Api::Success();
  }
  return Api::NewError(
      "%s expects receiver argument to be non-null and of"
      " type Instance.",
      CURRENT_FUNC);
}

DART_EXPORT Dart_Handle Dart_GetNativeStringArgument(Dart_NativeArguments args,
                                                     int arg_index,
                                                     void** peer) {
  NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
  TransitionNativeToVM transition(arguments->thread());
  Dart_Handle result = Api::Null();
  if (!GetNativeStringArgument(arguments, arg_index, &result, peer)) {
    return Api::NewArgumentError(
        "%s expects argument at %d to be of"
        " type String.",
        CURRENT_FUNC, arg_index);
  }
  return result;
}

DART_EXPORT Dart_Handle Dart_GetNativeIntegerArgument(Dart_NativeArguments args,
                                                      int index,
                                                      int64_t* value) {
  NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
  if ((index < 0) || (index >= arguments->NativeArgCount())) {
    return Api::NewError(
        "%s: argument 'index' out of range. Expected 0..%d but saw %d.",
        CURRENT_FUNC, arguments->NativeArgCount() - 1, index);
  }
  if (!GetNativeIntegerArgument(arguments, index, value)) {
    return Api::NewArgumentError(
        "%s: expects argument at %d to be of"
        " type Integer.",
        CURRENT_FUNC, index);
  }
  return Api::Success();
}

DART_EXPORT Dart_Handle Dart_GetNativeBooleanArgument(Dart_NativeArguments args,
                                                      int index,
                                                      bool* value) {
  NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
  if ((index < 0) || (index >= arguments->NativeArgCount())) {
    return Api::NewError(
        "%s: argument 'index' out of range. Expected 0..%d but saw %d.",
        CURRENT_FUNC, arguments->NativeArgCount() - 1, index);
  }
  if (!Api::GetNativeBooleanArgument(arguments, index, value)) {
    return Api::NewArgumentError(
        "%s: expects argument at %d to be of type Boolean.", CURRENT_FUNC,
        index);
  }
  return Api::Success();
}

DART_EXPORT Dart_Handle Dart_GetNativeDoubleArgument(Dart_NativeArguments args,
                                                     int index,
                                                     double* value) {
  NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
  if ((index < 0) || (index >= arguments->NativeArgCount())) {
    return Api::NewError(
        "%s: argument 'index' out of range. Expected 0..%d but saw %d.",
        CURRENT_FUNC, arguments->NativeArgCount() - 1, index);
  }
  if (!GetNativeDoubleArgument(arguments, index, value)) {
    return Api::NewArgumentError(
        "%s: expects argument at %d to be of"
        " type Double.",
        CURRENT_FUNC, index);
  }
  return Api::Success();
}

DART_EXPORT void Dart_SetReturnValue(Dart_NativeArguments args,
                                     Dart_Handle retval) {
  NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
  ASSERT(arguments->thread()->isolate() == Isolate::Current());
  ASSERT_CALLBACK_STATE(arguments->thread());
  TransitionNativeToVM transition(arguments->thread());
  if ((retval != Api::Null()) && !Api::IsInstance(retval) &&
      !Api::IsError(retval)) {
    // Print the current stack trace to make the problematic caller
    // easier to find.
    const StackTrace& stacktrace = GetCurrentStackTrace(0);
    OS::PrintErr("=== Current Trace:\n%s===\n", stacktrace.ToCString());

    const Object& ret_obj = Object::Handle(Api::UnwrapHandle(retval));
    FATAL1(
        "Return value check failed: saw '%s' expected a dart Instance or "
        "an Error.",
        ret_obj.ToCString());
  }
  ASSERT(retval != 0);
  Api::SetReturnValue(arguments, retval);
}

DART_EXPORT void Dart_SetWeakHandleReturnValue(Dart_NativeArguments args,
                                               Dart_WeakPersistentHandle rval) {
  NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
  TransitionNativeToVM transition(arguments->thread());
#if defined(DEBUG)
  Isolate* isolate = arguments->thread()->isolate();
  ASSERT(isolate == Isolate::Current());
  ASSERT(isolate->group()->api_state() != NULL &&
         (isolate->group()->api_state()->IsValidWeakPersistentHandle(rval)));
#endif
  Api::SetWeakHandleReturnValue(arguments, rval);
}

// --- Environment ---
StringPtr Api::GetEnvironmentValue(Thread* thread, const String& name) {
  String& result = String::Handle(CallEnvironmentCallback(thread, name));
  if (result.IsNull()) {
    // Every 'dart:X' library introduces an environment variable
    // 'dart.library.X' that is set to 'true'.
    // We just need to make sure to hide private libraries (starting with
    // "_", and the mirrors library, if it is not supported.

    if (!FLAG_enable_mirrors && name.Equals(Symbols::DartLibraryMirrors())) {
      return Symbols::False().raw();
    }

    if (!Api::IsFfiEnabled() && name.Equals(Symbols::DartLibraryFfi())) {
      return Symbols::False().raw();
    }

    if (name.Equals(Symbols::DartVMProduct())) {
#ifdef PRODUCT
      return Symbols::True().raw();
#else
      return Symbols::False().raw();
#endif
    }

    if (name.Equals(Symbols::DartDeveloperTimeline())) {
#ifdef SUPPORT_TIMELINE
      return Symbols::True().raw();
#else
      return Symbols::False().raw();
#endif
    }

    const String& prefix = Symbols::DartLibrary();
    if (name.StartsWith(prefix)) {
      const String& library_name =
          String::Handle(String::SubString(name, prefix.Length()));

      // Private libraries (starting with "_") are not exposed to the user.
      if (!library_name.IsNull() && library_name.CharAt(0) != '_') {
        const String& dart_library_name =
            String::Handle(String::Concat(Symbols::DartScheme(), library_name));
        const Library& library =
            Library::Handle(Library::LookupLibrary(thread, dart_library_name));
        if (!library.IsNull()) {
          return Symbols::True().raw();
        }
      }
    }
    // Check for default VM provided values. If it was not overridden on the
    // command line.
    if (Symbols::DartIsVM().Equals(name)) {
      return Symbols::True().raw();
    }
    if (FLAG_causal_async_stacks) {
      if (Symbols::DartDeveloperCausalAsyncStacks().Equals(name)) {
        return Symbols::True().raw();
      }
    }
  }
  return result.raw();
}

StringPtr Api::CallEnvironmentCallback(Thread* thread, const String& name) {
  Isolate* isolate = thread->isolate();
  Dart_EnvironmentCallback callback = isolate->environment_callback();
  if (callback != NULL) {
    Scope api_scope(thread);
    Dart_Handle api_name = Api::NewHandle(thread, name.raw());
    Dart_Handle api_response;
    {
      TransitionVMToNative transition(thread);
      api_response = callback(api_name);
    }
    const Object& response =
        Object::Handle(thread->zone(), Api::UnwrapHandle(api_response));
    if (response.IsString()) {
      return String::Cast(response).raw();
    } else if (response.IsError()) {
      Exceptions::ThrowArgumentError(
          String::Handle(String::New(Error::Cast(response).ToErrorCString())));
    } else if (!response.IsNull()) {
      // At this point everything except null are invalid environment values.
      Exceptions::ThrowArgumentError(
          String::Handle(String::New("Illegal environment value")));
    }
  }
  return String::null();
}

DART_EXPORT Dart_Handle
Dart_SetEnvironmentCallback(Dart_EnvironmentCallback callback) {
  Isolate* isolate = Isolate::Current();
  CHECK_ISOLATE(isolate);
  isolate->set_environment_callback(callback);
  return Api::Success();
}

// --- Scripts and Libraries ---
DART_EXPORT void Dart_SetBooleanReturnValue(Dart_NativeArguments args,
                                            bool retval) {
  NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
  TransitionNativeToVM transition(arguments->thread());
  ASSERT(arguments->thread()->isolate() == Isolate::Current());
  ASSERT_CALLBACK_STATE(arguments->thread());
  arguments->SetReturn(Bool::Get(retval));
}

DART_EXPORT void Dart_SetIntegerReturnValue(Dart_NativeArguments args,
                                            int64_t retval) {
  NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
  TransitionNativeToVM transition(arguments->thread());
  ASSERT(arguments->thread()->isolate() == Isolate::Current());
  ASSERT_CALLBACK_STATE(arguments->thread());
  if (Smi::IsValid(retval)) {
    Api::SetSmiReturnValue(arguments, static_cast<intptr_t>(retval));
  } else {
    // Slow path for Mints.
    Api::SetIntegerReturnValue(arguments, retval);
  }
}

DART_EXPORT void Dart_SetDoubleReturnValue(Dart_NativeArguments args,
                                           double retval) {
  NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
  ASSERT(arguments->thread()->isolate() == Isolate::Current());
  ASSERT_CALLBACK_STATE(arguments->thread());
  TransitionNativeToVM transition(arguments->thread());
  Api::SetDoubleReturnValue(arguments, retval);
}

// --- Scripts and Libraries ---

DART_EXPORT Dart_Handle
Dart_SetLibraryTagHandler(Dart_LibraryTagHandler handler) {
  Isolate* isolate = Isolate::Current();
  CHECK_ISOLATE(isolate);
  isolate->group()->set_library_tag_handler(handler);
  return Api::Success();
}

DART_EXPORT Dart_Handle Dart_DefaultCanonicalizeUrl(Dart_Handle base_url,
                                                    Dart_Handle url) {
  DARTSCOPE(Thread::Current());
  API_TIMELINE_DURATION(T);
  CHECK_CALLBACK_STATE(T);

  const String& base_uri = Api::UnwrapStringHandle(Z, base_url);
  if (base_uri.IsNull()) {
    RETURN_TYPE_ERROR(Z, base_url, String);
  }
  const String& uri = Api::UnwrapStringHandle(Z, url);
  if (uri.IsNull()) {
    RETURN_TYPE_ERROR(Z, url, String);
  }

  const char* resolved_uri;
  if (!ResolveUri(uri.ToCString(), base_uri.ToCString(), &resolved_uri)) {
    return Api::NewError("%s: Unable to canonicalize uri '%s'.", CURRENT_FUNC,
                         uri.ToCString());
  }
  return Api::NewHandle(T, String::New(resolved_uri));
}

DART_EXPORT Dart_Handle Dart_LoadScriptFromKernel(const uint8_t* buffer,
                                                  intptr_t buffer_size) {
#if defined(DART_PRECOMPILED_RUNTIME)
  return Api::NewError("%s: Cannot compile on an AOT runtime.", CURRENT_FUNC);
#else
  DARTSCOPE(Thread::Current());
  API_TIMELINE_DURATION(T);
  StackZone zone(T);
  Isolate* I = T->isolate();

  Library& library = Library::Handle(Z, I->object_store()->root_library());
  if (!library.IsNull()) {
    const String& library_url = String::Handle(Z, library.url());
    return Api::NewError("%s: A script has already been loaded from '%s'.",
                         CURRENT_FUNC, library_url.ToCString());
  }
  CHECK_CALLBACK_STATE(T);

  // NOTE: We do not attach a finalizer for this object, because the embedder
  // will free it once the isolate group has shutdown.
  const auto& td = ExternalTypedData::Handle(ExternalTypedData::New(
      kExternalTypedDataUint8ArrayCid, const_cast<uint8_t*>(buffer),
      buffer_size, Heap::kOld));

  const char* error = nullptr;
  std::unique_ptr<kernel::Program> program =
      kernel::Program::ReadFromTypedData(td, &error);
  if (program == nullptr) {
    return Api::NewError("Can't load Kernel binary: %s.", error);
  }
  if (I->is_service_isolate() || I->is_kernel_isolate()) {
    // For now the service isolate and kernel isolate will be running in
    // weak mode and we assert for that here.
    ASSERT(!I->null_safety());
  } else {
    // If null safety is not specified on the command line we use the value
    // from the dill file that the CFE has computed based on how it was invoked.
    if (FLAG_null_safety == kNullSafetyOptionUnspecified) {
      I->set_null_safety(program->compilation_mode() ==
                         NNBDCompiledMode::kStrong);
    }
  }
  const Object& tmp = kernel::KernelLoader::LoadEntireProgram(program.get());
  program.reset();

  if (tmp.IsError()) {
    return Api::NewHandle(T, tmp.raw());
  }

  I->source()->script_kernel_size = buffer_size;
  I->source()->script_kernel_buffer = buffer;

  // TODO(32618): Setting root library based on whether it has 'main' or not
  // is not correct because main can be in the exported namespace of a library
  // or it could be a getter.
  if (tmp.IsNull()) {
    return Api::NewError("%s: The binary program does not contain 'main'.",
                         CURRENT_FUNC);
  }
  library ^= tmp.raw();
  I->object_store()->set_root_library(library);
  return Api::NewHandle(T, library.raw());
#endif  // defined(DART_PRECOMPILED_RUNTIME)
}

DART_EXPORT Dart_Handle Dart_RootLibrary() {
  Thread* thread = Thread::Current();
  Isolate* isolate = thread->isolate();
  CHECK_ISOLATE(isolate);
  TransitionNativeToVM transition(thread);
  return Api::NewHandle(thread, isolate->object_store()->root_library());
}

DART_EXPORT Dart_Handle Dart_SetRootLibrary(Dart_Handle library) {
  DARTSCOPE(Thread::Current());
  const Object& obj = Object::Handle(Z, Api::UnwrapHandle(library));
  if (obj.IsNull() || obj.IsLibrary()) {
    Library& lib = Library::Handle(Z);
    lib ^= obj.raw();
    T->isolate()->object_store()->set_root_library(lib);
    return library;
  }
  RETURN_TYPE_ERROR(Z, library, Library);
}

DART_EXPORT Dart_Handle Dart_GetClass(Dart_Handle library,
                                      Dart_Handle class_name) {
  DARTSCOPE(Thread::Current());
  const Library& lib = Api::UnwrapLibraryHandle(Z, library);
  if (lib.IsNull()) {
    RETURN_TYPE_ERROR(Z, library, Library);
  }
  const String& cls_name = Api::UnwrapStringHandle(Z, class_name);
  if (cls_name.IsNull()) {
    RETURN_TYPE_ERROR(Z, class_name, String);
  }
  const Class& cls = Class::Handle(Z, lib.LookupClassAllowPrivate(cls_name));
  if (cls.IsNull()) {
    // TODO(turnidge): Return null or error in this case?
    const String& lib_name = String::Handle(Z, lib.name());
    return Api::NewError("Class '%s' not found in library '%s'.",
                         cls_name.ToCString(), lib_name.ToCString());
  }
  cls.EnsureDeclarationLoaded();
  CHECK_ERROR_HANDLE(cls.VerifyEntryPoint());
  return Api::NewHandle(T, cls.RareType());
}

static Dart_Handle GetTypeCommon(Dart_Handle library,
                                 Dart_Handle class_name,
                                 intptr_t number_of_type_arguments,
                                 Dart_Handle* type_arguments,
                                 Nullability nullability) {
  DARTSCOPE(Thread::Current());
  // Validate the input arguments.
  const Library& lib = Api::UnwrapLibraryHandle(Z, library);
  if (lib.IsNull()) {
    RETURN_TYPE_ERROR(Z, library, Library);
  }
  if (!lib.Loaded()) {
    return Api::NewError("%s expects library argument 'library' to be loaded.",
                         CURRENT_FUNC);
  }
  const String& name_str = Api::UnwrapStringHandle(Z, class_name);
  if (name_str.IsNull()) {
    RETURN_TYPE_ERROR(Z, class_name, String);
  }
  const Class& cls = Class::Handle(Z, lib.LookupClassAllowPrivate(name_str));
  if (cls.IsNull()) {
    const String& lib_name = String::Handle(Z, lib.name());
    return Api::NewError("Type '%s' not found in library '%s'.",
                         name_str.ToCString(), lib_name.ToCString());
  }
  cls.EnsureDeclarationLoaded();
  CHECK_ERROR_HANDLE(cls.VerifyEntryPoint());

  Type& type = Type::Handle();
  if (cls.NumTypeArguments() == 0) {
    if (number_of_type_arguments != 0) {
      return Api::NewError(
          "Invalid number of type arguments specified, "
          "got %" Pd " expected 0",
          number_of_type_arguments);
    }
    type ^= Type::NewNonParameterizedType(cls);
    type ^= type.ToNullability(nullability, Heap::kOld);
  } else {
    intptr_t num_expected_type_arguments = cls.NumTypeParameters();
    TypeArguments& type_args_obj = TypeArguments::Handle();
    if (number_of_type_arguments > 0) {
      if (type_arguments == NULL) {
        RETURN_NULL_ERROR(type_arguments);
      }
      if (num_expected_type_arguments != number_of_type_arguments) {
        return Api::NewError(
            "Invalid number of type arguments specified, "
            "got %" Pd " expected %" Pd,
            number_of_type_arguments, num_expected_type_arguments);
      }
      const Array& array = Api::UnwrapArrayHandle(Z, *type_arguments);
      if (array.IsNull()) {
        RETURN_TYPE_ERROR(Z, *type_arguments, Array);
      }
      if (array.Length() != num_expected_type_arguments) {
        return Api::NewError(
            "Invalid type arguments specified, expected an "
            "array of len %" Pd " but got an array of len %" Pd,
            number_of_type_arguments, array.Length());
      }
      // Set up the type arguments array.
      type_args_obj = TypeArguments::New(num_expected_type_arguments);
      AbstractType& type_arg = AbstractType::Handle();
      for (intptr_t i = 0; i < number_of_type_arguments; i++) {
        type_arg ^= array.At(i);
        type_args_obj.SetTypeAt(i, type_arg);
      }
    }

    // Construct the type object, canonicalize it and return.
    type ^=
        Type::New(cls, type_args_obj, TokenPosition::kNoSource, nullability);
  }
  type ^= ClassFinalizer::FinalizeType(cls, type);
  return Api::NewHandle(T, type.raw());
}

DART_EXPORT Dart_Handle Dart_GetType(Dart_Handle library,
                                     Dart_Handle class_name,
                                     intptr_t number_of_type_arguments,
                                     Dart_Handle* type_arguments) {
  return GetTypeCommon(library, class_name, number_of_type_arguments,
                       type_arguments, Nullability::kLegacy);
}

DART_EXPORT Dart_Handle Dart_GetNullableType(Dart_Handle library,
                                             Dart_Handle class_name,
                                             intptr_t number_of_type_arguments,
                                             Dart_Handle* type_arguments) {
  return GetTypeCommon(library, class_name, number_of_type_arguments,
                       type_arguments, Nullability::kNullable);
}

DART_EXPORT Dart_Handle
Dart_GetNonNullableType(Dart_Handle library,
                        Dart_Handle class_name,
                        intptr_t number_of_type_arguments,
                        Dart_Handle* type_arguments) {
  return GetTypeCommon(library, class_name, number_of_type_arguments,
                       type_arguments, Nullability::kNonNullable);
}

static Dart_Handle TypeToHelper(Dart_Handle type, Nullability nullability) {
  DARTSCOPE(Thread::Current());
  const Type& ty = Api::UnwrapTypeHandle(Z, type);
  if (ty.IsNull()) {
    RETURN_TYPE_ERROR(Z, type, Type);
  }
  if (ty.nullability() == nullability) {
    return type;
  }
  return Api::NewHandle(T, ty.ToNullability(nullability, Heap::kOld));
}

DART_EXPORT Dart_Handle Dart_TypeToNullableType(Dart_Handle type) {
  return TypeToHelper(type, Nullability::kNullable);
}

DART_EXPORT Dart_Handle Dart_TypeToNonNullableType(Dart_Handle type) {
  return TypeToHelper(type, Nullability::kNonNullable);
}

static Dart_Handle IsOfTypeNullabilityHelper(Dart_Handle type,
                                             Nullability nullability,
                                             bool* result) {
  DARTSCOPE(Thread::Current());
  const Type& ty = Api::UnwrapTypeHandle(Z, type);
  if (ty.IsNull()) {
    *result = false;
    RETURN_TYPE_ERROR(Z, type, Type);
  }
  *result = (ty.nullability() == nullability);
  return Api::Success();
}

DART_EXPORT Dart_Handle Dart_IsNullableType(Dart_Handle type, bool* result) {
  return IsOfTypeNullabilityHelper(type, Nullability::kNullable, result);
}

DART_EXPORT Dart_Handle Dart_IsNonNullableType(Dart_Handle type, bool* result) {
  return IsOfTypeNullabilityHelper(type, Nullability::kNonNullable, result);
}

DART_EXPORT Dart_Handle Dart_IsLegacyType(Dart_Handle type, bool* result) {
  return IsOfTypeNullabilityHelper(type, Nullability::kLegacy, result);
}

DART_EXPORT Dart_Handle Dart_LibraryUrl(Dart_Handle library) {
  DARTSCOPE(Thread::Current());
  const Library& lib = Api::UnwrapLibraryHandle(Z, library);
  if (lib.IsNull()) {
    RETURN_TYPE_ERROR(Z, library, Library);
  }
  const String& url = String::Handle(Z, lib.url());
  ASSERT(!url.IsNull());
  return Api::NewHandle(T, url.raw());
}

DART_EXPORT Dart_Handle Dart_LibraryResolvedUrl(Dart_Handle library) {
  DARTSCOPE(Thread::Current());
  const Library& lib = Api::UnwrapLibraryHandle(Z, library);
  if (lib.IsNull()) {
    RETURN_TYPE_ERROR(Z, library, Library);
  }
  const Class& toplevel = Class::Handle(lib.toplevel_class());
  ASSERT(!toplevel.IsNull());
  const Script& script = Script::Handle(toplevel.script());
  ASSERT(!script.IsNull());
  const String& url = String::Handle(script.resolved_url());
  ASSERT(!url.IsNull());
  return Api::NewHandle(T, url.raw());
}

DART_EXPORT Dart_Handle Dart_GetLoadedLibraries() {
  DARTSCOPE(Thread::Current());
  Isolate* I = T->isolate();

  const GrowableObjectArray& libs =
      GrowableObjectArray::Handle(Z, I->object_store()->libraries());
  int num_libs = libs.Length();

  // Create new list and populate with the loaded libraries.
  Library& lib = Library::Handle();
  const Array& library_list = Array::Handle(Z, Array::New(num_libs));
  for (int i = 0; i < num_libs; i++) {
    lib ^= libs.At(i);
    ASSERT(!lib.IsNull());
    library_list.SetAt(i, lib);
  }
  return Api::NewHandle(T, library_list.raw());
}

DART_EXPORT Dart_Handle Dart_LookupLibrary(Dart_Handle url) {
  DARTSCOPE(Thread::Current());
  const String& url_str = Api::UnwrapStringHandle(Z, url);
  if (url_str.IsNull()) {
    RETURN_TYPE_ERROR(Z, url, String);
  }
  const Library& library =
      Library::Handle(Z, Library::LookupLibrary(T, url_str));
  if (library.IsNull()) {
    return Api::NewError("%s: library '%s' not found.", CURRENT_FUNC,
                         url_str.ToCString());
  } else {
    return Api::NewHandle(T, library.raw());
  }
}

DART_EXPORT Dart_Handle Dart_LibraryHandleError(Dart_Handle library_in,
                                                Dart_Handle error_in) {
  DARTSCOPE(Thread::Current());

  const Library& lib = Api::UnwrapLibraryHandle(Z, library_in);
  if (lib.IsNull()) {
    RETURN_TYPE_ERROR(Z, library_in, Library);
  }
  const Instance& err = Api::UnwrapInstanceHandle(Z, error_in);
  if (err.IsNull()) {
    RETURN_TYPE_ERROR(Z, error_in, Instance);
  }
  CHECK_CALLBACK_STATE(T);

  return error_in;
}

DART_EXPORT Dart_Handle Dart_LoadLibraryFromKernel(const uint8_t* buffer,
                                                   intptr_t buffer_size) {
#if defined(DART_PRECOMPILED_RUNTIME)
  return Api::NewError("%s: Cannot compile on an AOT runtime.", CURRENT_FUNC);
#else
  DARTSCOPE(Thread::Current());
  API_TIMELINE_DURATION(T);
  StackZone zone(T);
  Isolate* I = T->isolate();

  CHECK_CALLBACK_STATE(T);

  // NOTE: We do not attach a finalizer for this object, because the embedder
  // will/should free it once the isolate group has shutdown.
  // See also http://dartbug.com/37030.
  const auto& td = ExternalTypedData::Handle(ExternalTypedData::New(
      kExternalTypedDataUint8ArrayCid, const_cast<uint8_t*>(buffer),
      buffer_size, Heap::kOld));

  const char* error = nullptr;
  std::unique_ptr<kernel::Program> program =
      kernel::Program::ReadFromTypedData(td, &error);
  if (program == nullptr) {
    return Api::NewError("Can't load Kernel binary: %s.", error);
  }
  if (I->is_service_isolate() || I->is_kernel_isolate()) {
    // For now the service isolate and kernel isolate will be running in
    // weak mode and we assert for that here.
    ASSERT(!I->null_safety());
  } else {
    // If null safety is not specified on the command line we use the value
    // from the dill file that the CFE has computed based on how it was invoked.
    if (FLAG_null_safety == kNullSafetyOptionUnspecified) {
      I->set_null_safety(program->compilation_mode() ==
                         NNBDCompiledMode::kStrong);
    }
  }
  const Object& result =
      kernel::KernelLoader::LoadEntireProgram(program.get(), false);
  program.reset();

  return Api::NewHandle(T, result.raw());
#endif  // defined(DART_PRECOMPILED_RUNTIME)
}

DART_EXPORT Dart_Handle Dart_GetImportsOfScheme(Dart_Handle scheme) {
  DARTSCOPE(Thread::Current());
  Isolate* I = T->isolate();
  const String& scheme_vm = Api::UnwrapStringHandle(Z, scheme);
  if (scheme_vm.IsNull()) {
    RETURN_TYPE_ERROR(Z, scheme, String);
  }

  const GrowableObjectArray& libraries =
      GrowableObjectArray::Handle(Z, I->object_store()->libraries());
  const GrowableObjectArray& result =
      GrowableObjectArray::Handle(Z, GrowableObjectArray::New());
  Library& importer = Library::Handle(Z);
  Array& imports = Array::Handle(Z);
  Namespace& ns = Namespace::Handle(Z);
  Library& importee = Library::Handle(Z);
  String& importee_uri = String::Handle(Z);
  for (intptr_t i = 0; i < libraries.Length(); i++) {
    importer ^= libraries.At(i);
    imports = importer.imports();
    for (intptr_t j = 0; j < imports.Length(); j++) {
      ns ^= imports.At(j);
      if (ns.IsNull()) continue;
      importee = ns.library();
      importee_uri = importee.url();
      if (importee_uri.StartsWith(scheme_vm)) {
        result.Add(importer);
        result.Add(importee);
      }
    }
  }

  return Api::NewHandle(T, Array::MakeFixedLength(result));
}

// Finalizes classes and invokes Dart core library function that completes
// futures of loadLibrary calls (deferred library loading).
DART_EXPORT Dart_Handle Dart_FinalizeLoading(bool complete_futures) {
  DARTSCOPE(Thread::Current());
  API_TIMELINE_DURATION(T);
  Isolate* I = T->isolate();
  CHECK_CALLBACK_STATE(T);

  // Finalize all classes if needed.
  Dart_Handle state = Api::CheckAndFinalizePendingClasses(T);
  if (Api::IsError(state)) {
    return state;
  }

#if !defined(PRODUCT)
  // Now that the newly loaded classes are finalized, notify the debugger
  // that new code has been loaded. If there are latent breakpoints in
  // the new code, the debugger convert them to unresolved source breakpoints.
  // The code that completes the futures (invoked below) may call into the
  // newly loaded code and trigger one of these breakpoints.
  I->debugger()->NotifyDoneLoading();
#endif

  // After having loaded all the code, we can let the GC set reaonsable limits
  // for the heap growth.
  // If this is an auxiliary isolate inside a larger isolate group, we will not
  // re-initialize the growth policy.
  if (I->group()->ContainsOnlyOneIsolate()) {
    I->heap()->old_space()->EvaluateAfterLoading();
  }

#if !defined(DART_PRECOMPILED_RUNTIME)
  if (FLAG_enable_mirrors) {
    // Notify mirrors that MirrorSystem.libraries needs to be recomputed.
    const Library& libmirrors = Library::Handle(Z, Library::MirrorsLibrary());
    const Field& dirty_bit = Field::Handle(
        Z, libmirrors.LookupLocalField(String::Handle(String::New("_dirty"))));
    ASSERT(!dirty_bit.IsNull() && dirty_bit.is_static());
    dirty_bit.SetStaticValue(Bool::True());
  }
#endif

  return Api::Success();
}

DART_EXPORT Dart_Handle
Dart_SetNativeResolver(Dart_Handle library,
                       Dart_NativeEntryResolver resolver,
                       Dart_NativeEntrySymbol symbol) {
  DARTSCOPE(Thread::Current());
  const Library& lib = Api::UnwrapLibraryHandle(Z, library);
  if (lib.IsNull()) {
    RETURN_TYPE_ERROR(Z, library, Library);
  }
  lib.set_native_entry_resolver(resolver);
  lib.set_native_entry_symbol_resolver(symbol);
  return Api::Success();
}

DART_EXPORT Dart_Handle
Dart_GetNativeResolver(Dart_Handle library,
                       Dart_NativeEntryResolver* resolver) {
  if (resolver == NULL) {
    RETURN_NULL_ERROR(resolver);
  }
  *resolver = NULL;
  DARTSCOPE(Thread::Current());
  const Library& lib = Api::UnwrapLibraryHandle(Z, library);
  if (lib.IsNull()) {
    RETURN_TYPE_ERROR(Z, library, Library);
  }
  *resolver = lib.native_entry_resolver();
  return Api::Success();
}

DART_EXPORT Dart_Handle Dart_GetNativeSymbol(Dart_Handle library,
                                             Dart_NativeEntrySymbol* resolver) {
  if (resolver == NULL) {
    RETURN_NULL_ERROR(resolver);
  }
  *resolver = NULL;
  DARTSCOPE(Thread::Current());
  const Library& lib = Api::UnwrapLibraryHandle(Z, library);
  if (lib.IsNull()) {
    RETURN_TYPE_ERROR(Z, library, Library);
  }
  *resolver = lib.native_entry_symbol_resolver();
  return Api::Success();
}

// --- Peer support ---

DART_EXPORT Dart_Handle Dart_GetPeer(Dart_Handle object, void** peer) {
  if (peer == NULL) {
    RETURN_NULL_ERROR(peer);
  }
  Thread* thread = Thread::Current();
  CHECK_ISOLATE(thread->isolate());
  TransitionNativeToVM transition(thread);
  REUSABLE_OBJECT_HANDLESCOPE(thread);
  Object& obj = thread->ObjectHandle();
  obj = Api::UnwrapHandle(object);
  if (obj.IsNull() || obj.IsNumber() || obj.IsBool()) {
    const char* msg =
        "%s: argument 'object' cannot be a subtype of Null, num, or bool";
    return Api::NewError(msg, CURRENT_FUNC);
  }
  {
    NoSafepointScope no_safepoint;
    ObjectPtr raw_obj = obj.raw();
    *peer = thread->isolate()->heap()->GetPeer(raw_obj);
  }
  return Api::Success();
}

DART_EXPORT Dart_Handle Dart_SetPeer(Dart_Handle object, void* peer) {
  Thread* thread = Thread::Current();
  CHECK_ISOLATE(thread->isolate());
  TransitionNativeToVM transition(thread);
  REUSABLE_OBJECT_HANDLESCOPE(thread);
  Object& obj = thread->ObjectHandle();
  obj = Api::UnwrapHandle(object);
  if (obj.IsNull() || obj.IsNumber() || obj.IsBool()) {
    const char* msg =
        "%s: argument 'object' cannot be a subtype of Null, num, or bool";
    return Api::NewError(msg, CURRENT_FUNC);
  }
  {
    NoSafepointScope no_safepoint;
    ObjectPtr raw_obj = obj.raw();
    thread->isolate()->heap()->SetPeer(raw_obj, peer);
  }
  return Api::Success();
}

// --- Dart Front-End (Kernel) support ---

DART_EXPORT bool Dart_IsKernelIsolate(Dart_Isolate isolate) {
#if defined(DART_PRECOMPILED_RUNTIME)
  return false;
#else
  Isolate* iso = reinterpret_cast<Isolate*>(isolate);
  return KernelIsolate::IsKernelIsolate(iso);
#endif
}

DART_EXPORT bool Dart_KernelIsolateIsRunning() {
#if defined(DART_PRECOMPILED_RUNTIME)
  return false;
#else
  return KernelIsolate::IsRunning();
#endif
}

DART_EXPORT Dart_Port Dart_KernelPort() {
#if defined(DART_PRECOMPILED_RUNTIME)
  return false;
#else
  return KernelIsolate::KernelPort();
#endif
}

DART_EXPORT Dart_KernelCompilationResult
Dart_CompileToKernel(const char* script_uri,
                     const uint8_t* platform_kernel,
                     intptr_t platform_kernel_size,
                     bool incremental_compile,
                     const char* package_config) {
  API_TIMELINE_DURATION(Thread::Current());

  Dart_KernelCompilationResult result = {};
#if defined(DART_PRECOMPILED_RUNTIME)
  result.status = Dart_KernelCompilationStatus_Unknown;
  result.error = strdup("Dart_CompileToKernel is unsupported.");
#else
  result = KernelIsolate::CompileToKernel(script_uri, platform_kernel,
                                          platform_kernel_size, 0, NULL,
                                          incremental_compile, package_config);
  if (result.status == Dart_KernelCompilationStatus_Ok) {
    Dart_KernelCompilationResult accept_result =
        KernelIsolate::AcceptCompilation();
    if (accept_result.status != Dart_KernelCompilationStatus_Ok) {
      FATAL1(
          "An error occurred in the CFE while accepting the most recent"
          " compilation results: %s",
          accept_result.error);
    }
  }
#endif
  return result;
}

DART_EXPORT Dart_KernelCompilationResult
Dart_CompileSourcesToKernel(const char* script_uri,
                            const uint8_t* platform_kernel,
                            intptr_t platform_kernel_size,
                            int source_files_count,
                            Dart_SourceFile sources[],
                            bool incremental_compile,
                            const char* package_config,
                            const char* multiroot_filepaths,
                            const char* multiroot_scheme) {
  Dart_KernelCompilationResult result = {};
#if defined(DART_PRECOMPILED_RUNTIME)
  result.status = Dart_KernelCompilationStatus_Unknown;
  result.error = strdup("Dart_CompileSourcesToKernel is unsupported.");
#else
  result = KernelIsolate::CompileToKernel(
      script_uri, platform_kernel, platform_kernel_size, source_files_count,
      sources, incremental_compile, package_config, multiroot_filepaths,
      multiroot_scheme);
  if (result.status == Dart_KernelCompilationStatus_Ok) {
    if (KernelIsolate::AcceptCompilation().status !=
        Dart_KernelCompilationStatus_Ok) {
      FATAL(
          "An error occurred in the CFE while accepting the most recent"
          " compilation results.");
    }
  }
#endif
  return result;
}

DART_EXPORT Dart_KernelCompilationResult Dart_KernelListDependencies() {
  Dart_KernelCompilationResult result = {};
#if defined(DART_PRECOMPILED_RUNTIME)
  result.status = Dart_KernelCompilationStatus_Unknown;
  result.error = strdup("Dart_KernelListDependencies is unsupported.");
#else
  result = KernelIsolate::ListDependencies();
#endif
  return result;
}

DART_EXPORT void Dart_SetDartLibrarySourcesKernel(
    const uint8_t* platform_kernel,
    const intptr_t platform_kernel_size) {
#if !defined(PRODUCT)
  Service::SetDartLibraryKernelForSources(platform_kernel,
                                          platform_kernel_size);
#endif
}

// --- Service support ---

DART_EXPORT bool Dart_IsServiceIsolate(Dart_Isolate isolate) {
  Isolate* iso = reinterpret_cast<Isolate*>(isolate);
  return ServiceIsolate::IsServiceIsolate(iso);
}

DART_EXPORT int64_t Dart_TimelineGetMicros() {
  return OS::GetCurrentMonotonicMicros();
}

DART_EXPORT void Dart_RegisterIsolateServiceRequestCallback(
    const char* name,
    Dart_ServiceRequestCallback callback,
    void* user_data) {
#if !defined(PRODUCT)
  Service::RegisterIsolateEmbedderCallback(name, callback, user_data);
#endif
}

DART_EXPORT void Dart_RegisterRootServiceRequestCallback(
    const char* name,
    Dart_ServiceRequestCallback callback,
    void* user_data) {
#if !defined(PRODUCT)
  Service::RegisterRootEmbedderCallback(name, callback, user_data);
#endif
}

DART_EXPORT void Dart_SetEmbedderInformationCallback(
    Dart_EmbedderInformationCallback callback) {
#if !defined(PRODUCT)
  Service::SetEmbedderInformationCallback(callback);
#endif
}

DART_EXPORT char* Dart_SetServiceStreamCallbacks(
    Dart_ServiceStreamListenCallback listen_callback,
    Dart_ServiceStreamCancelCallback cancel_callback) {
#if defined(PRODUCT)
  return NULL;
#else
  if (listen_callback != NULL) {
    if (Service::stream_listen_callback() != NULL) {
      return strdup(
          "Dart_SetServiceStreamCallbacks "
          "permits only one listen callback to be registered, please "
          "remove the existing callback and then add this callback");
    }
  } else {
    if (Service::stream_listen_callback() == NULL) {
      return strdup(
          "Dart_SetServiceStreamCallbacks "
          "expects 'listen_callback' to be present in the callback set.");
    }
  }
  if (cancel_callback != NULL) {
    if (Service::stream_cancel_callback() != NULL) {
      return strdup(
          "Dart_SetServiceStreamCallbacks "
          "permits only one cancel callback to be registered, please "
          "remove the existing callback and then add this callback");
    }
  } else {
    if (Service::stream_cancel_callback() == NULL) {
      return strdup(
          "Dart_SetServiceStreamCallbacks "
          "expects 'cancel_callback' to be present in the callback set.");
    }
  }
  Service::SetEmbedderStreamCallbacks(listen_callback, cancel_callback);
  return NULL;
#endif
}

DART_EXPORT void Dart_SetNativeServiceStreamCallback(
    Dart_NativeStreamConsumer consumer,
    const char* stream_id) {
#if !defined(PRODUCT)
  Service::SetNativeServiceStreamCallback(consumer, stream_id);
#endif
}

DART_EXPORT Dart_Handle Dart_ServiceSendDataEvent(const char* stream_id,
                                                  const char* event_kind,
                                                  const uint8_t* bytes,
                                                  intptr_t bytes_length) {
#if !defined(PRODUCT)
  DARTSCOPE(Thread::Current());
  Isolate* I = T->isolate();
  if (stream_id == NULL) {
    RETURN_NULL_ERROR(stream_id);
  }
  if (event_kind == NULL) {
    RETURN_NULL_ERROR(event_kind);
  }
  if (bytes == NULL) {
    RETURN_NULL_ERROR(bytes);
  }
  if (bytes_length < 0) {
    return Api::NewError("%s expects argument 'bytes_length' to be >= 0.",
                         CURRENT_FUNC);
  }
  Service::SendEmbedderEvent(I, stream_id, event_kind, bytes, bytes_length);
#endif
  return Api::Success();
}

DART_EXPORT char* Dart_SetFileModifiedCallback(
    Dart_FileModifiedCallback file_modified_callback) {
#if !defined(PRODUCT)
#if !defined(DART_PRECOMPILED_RUNTIME)
  if (file_modified_callback != NULL) {
    if (IsolateGroupReloadContext::file_modified_callback() != NULL) {
      return strdup(
          "Dart_SetFileModifiedCallback permits only one callback to be"
          " registered, please remove the existing callback and then add"
          " this callback");
    }
  } else {
    if (IsolateGroupReloadContext::file_modified_callback() == NULL) {
      return strdup(
          "Dart_SetFileModifiedCallback expects 'file_modified_callback' to"
          " be set before it is cleared.");
    }
  }
  IsolateGroupReloadContext::SetFileModifiedCallback(file_modified_callback);
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
#endif  // !defined(PRODUCT)
  return NULL;
}

DART_EXPORT bool Dart_IsReloading() {
#if defined(PRODUCT) || defined(DART_PRECOMPILED_RUNTIME)
  return false;
#else
  Thread* thread = Thread::Current();
  Isolate* isolate = thread->isolate();
  CHECK_ISOLATE(isolate);
  return isolate->group()->IsReloading();
#endif
}

DART_EXPORT void Dart_GlobalTimelineSetRecordedStreams(int64_t stream_mask) {
#if defined(SUPPORT_TIMELINE)
  const bool api_enabled = (stream_mask & DART_TIMELINE_STREAM_API) != 0;
  const bool compiler_enabled =
      (stream_mask & DART_TIMELINE_STREAM_COMPILER) != 0;
  const bool dart_enabled = (stream_mask & DART_TIMELINE_STREAM_DART) != 0;
  const bool debugger_enabled =
      (stream_mask & DART_TIMELINE_STREAM_DEBUGGER) != 0;
  const bool embedder_enabled =
      (stream_mask & DART_TIMELINE_STREAM_EMBEDDER) != 0;
  const bool gc_enabled = (stream_mask & DART_TIMELINE_STREAM_GC) != 0;
  const bool isolate_enabled =
      (stream_mask & DART_TIMELINE_STREAM_ISOLATE) != 0;
  const bool vm_enabled = (stream_mask & DART_TIMELINE_STREAM_VM) != 0;
  Timeline::SetStreamAPIEnabled(api_enabled);
  Timeline::SetStreamCompilerEnabled(compiler_enabled);
  Timeline::SetStreamDartEnabled(dart_enabled);
  Timeline::SetStreamDebuggerEnabled(debugger_enabled);
  Timeline::SetStreamEmbedderEnabled(embedder_enabled);
  Timeline::SetStreamGCEnabled(gc_enabled);
  Timeline::SetStreamIsolateEnabled(isolate_enabled);
  Timeline::SetStreamVMEnabled(vm_enabled);
#endif
}

DART_EXPORT void Dart_TimelineEvent(const char* label,
                                    int64_t timestamp0,
                                    int64_t timestamp1_or_async_id,
                                    Dart_Timeline_Event_Type type,
                                    intptr_t argument_count,
                                    const char** argument_names,
                                    const char** argument_values) {
#if defined(SUPPORT_TIMELINE)
  if (type < Dart_Timeline_Event_Begin) {
    return;
  }
  if (type > Dart_Timeline_Event_Flow_End) {
    return;
  }
  TimelineStream* stream = Timeline::GetEmbedderStream();
  ASSERT(stream != NULL);
  TimelineEvent* event = stream->StartEvent();
  if (event == NULL) {
    return;
  }
  switch (type) {
    case Dart_Timeline_Event_Begin:
      event->Begin(label, timestamp0);
      break;
    case Dart_Timeline_Event_End:
      event->End(label, timestamp0);
      break;
    case Dart_Timeline_Event_Instant:
      event->Instant(label, timestamp0);
      break;
    case Dart_Timeline_Event_Duration:
      event->Duration(label, timestamp0, timestamp1_or_async_id);
      break;
    case Dart_Timeline_Event_Async_Begin:
      event->AsyncBegin(label, timestamp1_or_async_id, timestamp0);
      break;
    case Dart_Timeline_Event_Async_End:
      event->AsyncEnd(label, timestamp1_or_async_id, timestamp0);
      break;
    case Dart_Timeline_Event_Async_Instant:
      event->AsyncInstant(label, timestamp1_or_async_id, timestamp0);
      break;
    case Dart_Timeline_Event_Counter:
      event->Counter(label, timestamp0);
      break;
    case Dart_Timeline_Event_Flow_Begin:
      event->FlowBegin(label, timestamp1_or_async_id, timestamp0);
      break;
    case Dart_Timeline_Event_Flow_Step:
      event->FlowStep(label, timestamp1_or_async_id, timestamp0);
      break;
    case Dart_Timeline_Event_Flow_End:
      event->FlowEnd(label, timestamp1_or_async_id, timestamp0);
      break;
    default:
      FATAL("Unknown Dart_Timeline_Event_Type");
  }
  event->SetNumArguments(argument_count);
  for (intptr_t i = 0; i < argument_count; i++) {
    event->CopyArgument(i, argument_names[i], argument_values[i]);
  }
  event->Complete();
#endif
}

DART_EXPORT void Dart_SetThreadName(const char* name) {
  OSThread* thread = OSThread::Current();
  if (thread == NULL) {
    // VM is shutting down.
    return;
  }
  thread->SetName(name);
}

DART_EXPORT
Dart_Handle Dart_SaveCompilationTrace(uint8_t** buffer,
                                      intptr_t* buffer_length) {
#if defined(DART_PRECOMPILED_RUNTIME)
  return Api::NewError("%s: Cannot compile on an AOT runtime.", CURRENT_FUNC);
#else
  Thread* thread = Thread::Current();
  API_TIMELINE_DURATION(thread);
  DARTSCOPE(thread);
  CHECK_NULL(buffer);
  CHECK_NULL(buffer_length);
  CompilationTraceSaver saver(thread->zone());
  ProgramVisitor::WalkProgram(thread->zone(), thread->isolate(), &saver);
  saver.StealBuffer(buffer, buffer_length);
  return Api::Success();
#endif  // defined(DART_PRECOMPILED_RUNTIME)
}

DART_EXPORT
Dart_Handle Dart_SaveTypeFeedback(uint8_t** buffer, intptr_t* buffer_length) {
#if defined(DART_PRECOMPILED_RUNTIME)
  return Api::NewError("%s: Cannot compile on an AOT runtime.", CURRENT_FUNC);
#else
  Thread* thread = Thread::Current();
  API_TIMELINE_DURATION(thread);
  DARTSCOPE(thread);
  CHECK_NULL(buffer);
  CHECK_NULL(buffer_length);

  WriteStream stream(buffer, ApiReallocate, MB);
  TypeFeedbackSaver saver(&stream);
  saver.WriteHeader();
  saver.SaveClasses();
  saver.SaveFields();
  ProgramVisitor::WalkProgram(thread->zone(), thread->isolate(), &saver);
  *buffer_length = stream.bytes_written();

  return Api::Success();
#endif  // defined(DART_PRECOMPILED_RUNTIME)
}

DART_EXPORT
Dart_Handle Dart_LoadCompilationTrace(uint8_t* buffer, intptr_t buffer_length) {
#if defined(DART_PRECOMPILED_RUNTIME)
  return Api::NewError("%s: Cannot compile on an AOT runtime.", CURRENT_FUNC);
#else
  Thread* thread = Thread::Current();
  API_TIMELINE_DURATION(thread);
  DARTSCOPE(thread);
  CHECK_NULL(buffer);
  Dart_Handle state = Api::CheckAndFinalizePendingClasses(T);
  if (Api::IsError(state)) {
    return state;
  }
  CompilationTraceLoader loader(thread);
  const Object& error =
      Object::Handle(loader.CompileTrace(buffer, buffer_length));
  if (error.IsError()) {
    return Api::NewHandle(T, Error::Cast(error).raw());
  }
  return Api::Success();
#endif  // defined(DART_PRECOMPILED_RUNTIME)
}

DART_EXPORT
Dart_Handle Dart_LoadTypeFeedback(uint8_t* buffer, intptr_t buffer_length) {
#if defined(DART_PRECOMPILED_RUNTIME)
  return Api::NewError("%s: Cannot compile on an AOT runtime.", CURRENT_FUNC);
#else
  Thread* thread = Thread::Current();
  API_TIMELINE_DURATION(thread);
  DARTSCOPE(thread);
  CHECK_NULL(buffer);
  Dart_Handle state = Api::CheckAndFinalizePendingClasses(T);
  if (Api::IsError(state)) {
    return state;
  }
  ReadStream stream(buffer, buffer_length);
  TypeFeedbackLoader loader(thread);
  const Object& error = Object::Handle(loader.LoadFeedback(&stream));
  if (error.IsError()) {
    return Api::NewHandle(T, Error::Cast(error).raw());
  }
  return Api::Success();
#endif  // defined(DART_PRECOMPILED_RUNTIME)
}

DART_EXPORT Dart_Handle Dart_SortClasses() {
#if defined(DART_PRECOMPILED_RUNTIME)
  return Api::NewError("%s: Cannot compile on an AOT runtime.", CURRENT_FUNC);
#else
  DARTSCOPE(Thread::Current());
  // Prevent background compiler from running while code is being cleared and
  // adding new code.
  BackgroundCompiler::Stop(Isolate::Current());
  // We don't have mechanisms to change class-ids that are embedded in code and
  // ICData.
  ClassFinalizer::ClearAllCode();
  // Make sure that ICData etc. that have been cleared are also removed from
  // the heap so that they are not found by the heap verifier.
  Isolate::Current()->heap()->CollectAllGarbage();
  ClassFinalizer::SortClasses();
  return Api::Success();
#endif  // defined(DART_PRECOMPILED_RUNTIME)
}

DART_EXPORT Dart_Handle Dart_Precompile() {
#if defined(TARGET_ARCH_IA32)
  return Api::NewError("AOT compilation is not supported on IA32.");
#elif !defined(DART_PRECOMPILER)
  return Api::NewError(
      "This VM was built without support for AOT compilation.");
#else
  DARTSCOPE(Thread::Current());
  API_TIMELINE_BEGIN_END(T);
  if (!FLAG_precompiled_mode) {
    return Api::NewError("Flag --precompilation was not specified.");
  }
  Dart_Handle result = Api::CheckAndFinalizePendingClasses(T);
  if (Api::IsError(result)) {
    return result;
  }
  CHECK_CALLBACK_STATE(T);
  CompilerState state(Thread::Current(), /*is_aot=*/true);
  CHECK_ERROR_HANDLE(Precompiler::CompileAll());
  return Api::Success();
#endif
}

// Used for StreamingWriteStream/BlobImageWriter sizes for ELF and blobs.
#if !defined(TARGET_ARCH_IA32) && defined(DART_PRECOMPILER)
static const intptr_t kInitialSize = 2 * MB;
static const intptr_t kInitialDebugSize = 1 * MB;
#endif

DART_EXPORT Dart_Handle
Dart_CreateAppAOTSnapshotAsAssembly(Dart_StreamingWriteCallback callback,
                                    void* callback_data,
                                    bool strip,
                                    void* debug_callback_data) {
#if defined(TARGET_ARCH_IA32)
  return Api::NewError("AOT compilation is not supported on IA32.");
#elif defined(TARGET_OS_WINDOWS)
  return Api::NewError("Assembly generation is not implemented for Windows.");
#elif !defined(DART_PRECOMPILER)
  return Api::NewError(
      "This VM was built without support for AOT compilation.");
#else
  DARTSCOPE(Thread::Current());
  API_TIMELINE_DURATION(T);
  CHECK_NULL(callback);

  TIMELINE_DURATION(T, Isolate, "WriteAppAOTSnapshot");
  const bool generate_debug = debug_callback_data != nullptr;

  StreamingWriteStream debug_stream(generate_debug ? kInitialDebugSize : 0,
                                    callback, debug_callback_data);

  Elf* elf = generate_debug ? new (Z) Elf(Z, &debug_stream) : nullptr;

  AssemblyImageWriter image_writer(T, callback, callback_data, strip, elf);
  uint8_t* vm_snapshot_data_buffer = NULL;
  uint8_t* isolate_snapshot_data_buffer = NULL;
  FullSnapshotWriter writer(Snapshot::kFullAOT, &vm_snapshot_data_buffer,
                            &isolate_snapshot_data_buffer, ApiReallocate,
                            &image_writer, &image_writer);

  writer.WriteFullSnapshot();
  image_writer.Finalize();
  if (elf != nullptr) {
    elf->Finalize();
  }

  return Api::Success();
#endif
}

DART_EXPORT Dart_Handle
Dart_CreateVMAOTSnapshotAsAssembly(Dart_StreamingWriteCallback callback,
                                   void* callback_data) {
#if defined(TARGET_ARCH_IA32)
  return Api::NewError("AOT compilation is not supported on IA32.");
#elif defined(TARGET_OS_WINDOWS)
  return Api::NewError("Assembly generation is not implemented for Windows.");
#elif !defined(DART_PRECOMPILER)
  return Api::NewError(
      "This VM was built without support for AOT compilation.");
#else
  DARTSCOPE(Thread::Current());
  API_TIMELINE_DURATION(T);
  CHECK_NULL(callback);

  TIMELINE_DURATION(T, Isolate, "WriteVMAOTSnapshot");
  AssemblyImageWriter image_writer(T, callback, callback_data);
  uint8_t* vm_snapshot_data_buffer = nullptr;
  FullSnapshotWriter writer(Snapshot::kFullAOT, &vm_snapshot_data_buffer,
                            nullptr, ApiReallocate, &image_writer, nullptr);

  writer.WriteFullSnapshot();

  return Api::Success();
#endif
}

DART_EXPORT Dart_Handle
Dart_CreateAppAOTSnapshotAsElf(Dart_StreamingWriteCallback callback,
                               void* callback_data,
                               bool strip,
                               void* debug_callback_data) {
#if defined(TARGET_ARCH_IA32)
  return Api::NewError("AOT compilation is not supported on IA32.");
#elif !defined(DART_PRECOMPILER)
  return Api::NewError(
      "This VM was built without support for AOT compilation.");
#else
  DARTSCOPE(Thread::Current());
  API_TIMELINE_DURATION(T);

  NOT_IN_PRODUCT(TimelineBeginEndScope tbes2(T, Timeline::GetIsolateStream(),
                                             "WriteAppAOTSnapshot"));

  uint8_t* vm_snapshot_data_buffer = nullptr;
  uint8_t* vm_snapshot_instructions_buffer = nullptr;
  uint8_t* isolate_snapshot_data_buffer = nullptr;
  uint8_t* isolate_snapshot_instructions_buffer = nullptr;

  const bool generate_debug = debug_callback_data != nullptr;

  StreamingWriteStream elf_stream(kInitialSize, callback, callback_data);
  StreamingWriteStream debug_stream(generate_debug ? kInitialDebugSize : 0,
                                    callback, debug_callback_data);

  Elf* elf = new (Z) Elf(Z, &elf_stream);
  Dwarf* elf_dwarf = strip ? nullptr : new (Z) Dwarf(Z, nullptr, elf);
  Elf* debug_elf = generate_debug ? new (Z) Elf(Z, &debug_stream) : nullptr;
  Dwarf* debug_dwarf =
      generate_debug ? new (Z) Dwarf(Z, nullptr, debug_elf) : nullptr;

  // Note that the BSS section must come first because it cannot be placed in
  // between any two non-writable segments, due to a bug in Jelly Bean's ELF
  // loader. See also Elf::WriteProgramTable().
  const intptr_t bss_base =
      elf->AddBSSData("_kDartBSSData", sizeof(compiler::target::uword));
  // Add the BSS section to the separately saved debugging information, even
  // though there will be no code in it to relocate, since it precedes the
  // .text sections and thus affects their virtual addresses.
  if (debug_dwarf != nullptr) {
    debug_elf->AddBSSData("_kDartBSSData", sizeof(compiler::target::uword));
  }

  BlobImageWriter vm_image_writer(T, &vm_snapshot_instructions_buffer,
                                  ApiReallocate, kInitialSize, debug_dwarf,
                                  bss_base, elf, elf_dwarf);
  BlobImageWriter isolate_image_writer(T, &isolate_snapshot_instructions_buffer,
                                       ApiReallocate, kInitialSize, debug_dwarf,
                                       bss_base, elf, elf_dwarf);
  FullSnapshotWriter writer(Snapshot::kFullAOT, &vm_snapshot_data_buffer,
                            &isolate_snapshot_data_buffer, ApiReallocate,
                            &vm_image_writer, &isolate_image_writer);

  writer.WriteFullSnapshot();
  elf->AddROData("_kDartVmSnapshotData", vm_snapshot_data_buffer,
                 writer.VmIsolateSnapshotSize());
  elf->AddROData("_kDartIsolateSnapshotData", isolate_snapshot_data_buffer,
                 writer.IsolateSnapshotSize());

  if (elf_dwarf != nullptr) {
    // TODO(rmacnak): Generate .debug_frame / .eh_frame / .arm.exidx to
    // provide unwinding information.
    elf_dwarf->Write();
  }
  elf->Finalize();
  if (generate_debug) {
    debug_dwarf->Write();
    debug_elf->Finalize();
  }

  return Api::Success();
#endif
}

#if (!defined(TARGET_ARCH_IA32) && !defined(DART_PRECOMPILED_RUNTIME))

// Any flag that affects how we compile code might cause a problem when the
// snapshot writer generates code with one value of the flag and the snapshot
// reader expects code to behave according to another value of the flag.
// Normally, we add these flags to Dart::FeaturesString and refuse to run the
// snapshot it they don't match, but since --interpret-irregexp affects only
// 2 functions we choose to remove the code instead. See issue #34422.
static void DropRegExpMatchCode(Zone* zone) {
  const String& execute_match_name =
      String::Handle(zone, String::New("_ExecuteMatch"));
  const String& execute_match_sticky_name =
      String::Handle(zone, String::New("_ExecuteMatchSticky"));

  const Library& core_lib = Library::Handle(zone, Library::CoreLibrary());
  const Class& reg_exp_class =
      Class::Handle(zone, core_lib.LookupClassAllowPrivate(Symbols::_RegExp()));
  ASSERT(!reg_exp_class.IsNull());

  Function& func = Function::Handle(
      zone, reg_exp_class.LookupFunctionAllowPrivate(execute_match_name));
  ASSERT(!func.IsNull());
  Code& code = Code::Handle(zone);
  if (func.HasCode()) {
    code = func.CurrentCode();
    ASSERT(!code.IsNull());
    code.DisableDartCode();
  }
  func.ClearCode();
  func.ClearICDataArray();
  ASSERT(!func.HasCode());

  func = reg_exp_class.LookupFunctionAllowPrivate(execute_match_sticky_name);
  ASSERT(!func.IsNull());
  if (func.HasCode()) {
    code = func.CurrentCode();
    ASSERT(!code.IsNull());
    code.DisableDartCode();
  }
  func.ClearCode();
  func.ClearICDataArray();
  ASSERT(!func.HasCode());
}

#endif  // (!defined(TARGET_ARCH_IA32) && !defined(DART_PRECOMPILED_RUNTIME))

DART_EXPORT Dart_Handle Dart_CreateCoreJITSnapshotAsBlobs(
    uint8_t** vm_snapshot_data_buffer,
    intptr_t* vm_snapshot_data_size,
    uint8_t** vm_snapshot_instructions_buffer,
    intptr_t* vm_snapshot_instructions_size,
    uint8_t** isolate_snapshot_data_buffer,
    intptr_t* isolate_snapshot_data_size,
    uint8_t** isolate_snapshot_instructions_buffer,
    intptr_t* isolate_snapshot_instructions_size) {
#if defined(TARGET_ARCH_IA32)
  return Api::NewError("Snapshots with code are not supported on IA32.");
#elif defined(DART_PRECOMPILED_RUNTIME)
  return Api::NewError("JIT app snapshots cannot be taken from an AOT runtime");
#else
  DARTSCOPE(Thread::Current());
  API_TIMELINE_DURATION(T);
  Isolate* I = T->isolate();
  CHECK_NULL(vm_snapshot_data_buffer);
  CHECK_NULL(vm_snapshot_data_size);
  CHECK_NULL(vm_snapshot_instructions_buffer);
  CHECK_NULL(vm_snapshot_instructions_size);
  CHECK_NULL(isolate_snapshot_data_buffer);
  CHECK_NULL(isolate_snapshot_data_size);
  CHECK_NULL(isolate_snapshot_instructions_buffer);
  CHECK_NULL(isolate_snapshot_instructions_size);
  // Finalize all classes if needed.
  Dart_Handle state = Api::CheckAndFinalizePendingClasses(T);
  if (Api::IsError(state)) {
    return state;
  }
  BackgroundCompiler::Stop(I);
  DropRegExpMatchCode(Z);

  ProgramVisitor::Dedup(T);
  Symbols::Compact();

  TIMELINE_DURATION(T, Isolate, "WriteCoreJITSnapshot");
  BlobImageWriter vm_image_writer(T, vm_snapshot_instructions_buffer,
                                  ApiReallocate, 2 * MB /* initial_size */);
  BlobImageWriter isolate_image_writer(T, isolate_snapshot_instructions_buffer,
                                       ApiReallocate,
                                       2 * MB /* initial_size */);
  FullSnapshotWriter writer(Snapshot::kFullJIT, vm_snapshot_data_buffer,
                            isolate_snapshot_data_buffer, ApiReallocate,
                            &vm_image_writer, &isolate_image_writer);
  writer.WriteFullSnapshot();

  *vm_snapshot_data_size = writer.VmIsolateSnapshotSize();
  *vm_snapshot_instructions_size = vm_image_writer.InstructionsBlobSize();
  *isolate_snapshot_data_size = writer.IsolateSnapshotSize();
  *isolate_snapshot_instructions_size =
      isolate_image_writer.InstructionsBlobSize();

  return Api::Success();
#endif
}

#if !defined(TARGET_ARCH_IA32) && !defined(DART_PRECOMPILED_RUNTIME)
static void KillNonMainIsolatesSlow(Thread* thread, Isolate* main_isolate) {
  auto group = main_isolate->group();
  while (true) {
    bool non_main_isolates_alive = false;
    {
      SafepointOperationScope safepoint(thread);
      group->ForEachIsolate([&](Isolate* isolate) {
        if (isolate != main_isolate) {
          Isolate::KillIfExists(isolate, Isolate::kKillMsg);
          non_main_isolates_alive = true;
        }
      });
      if (!non_main_isolates_alive) {
        break;
      }
    }
    OS::SleepMicros(10 * 1000);
  }
}
#endif  // !defined(TARGET_ARCH_IA32) && !defined(DART_PRECOMPILED_RUNTIME)

DART_EXPORT Dart_Handle
Dart_CreateAppJITSnapshotAsBlobs(uint8_t** isolate_snapshot_data_buffer,
                                 intptr_t* isolate_snapshot_data_size,
                                 uint8_t** isolate_snapshot_instructions_buffer,
                                 intptr_t* isolate_snapshot_instructions_size) {
#if defined(TARGET_ARCH_IA32)
  return Api::NewError("Snapshots with code are not supported on IA32.");
#elif defined(DART_PRECOMPILED_RUNTIME)
  return Api::NewError("JIT app snapshots cannot be taken from an AOT runtime");
#else
  DARTSCOPE(Thread::Current());
  API_TIMELINE_DURATION(T);
  Isolate* I = T->isolate();
  CHECK_NULL(isolate_snapshot_data_buffer);
  CHECK_NULL(isolate_snapshot_data_size);
  CHECK_NULL(isolate_snapshot_instructions_buffer);
  CHECK_NULL(isolate_snapshot_instructions_size);

  // Finalize all classes if needed.
  Dart_Handle state = Api::CheckAndFinalizePendingClasses(T);
  if (Api::IsError(state)) {
    return state;
  }

  // Kill off any auxiliary isolates before starting with deduping.
  KillNonMainIsolatesSlow(T, I);

  BackgroundCompiler::Stop(I);
  DropRegExpMatchCode(Z);

  ProgramVisitor::Dedup(T);
  Symbols::Compact();

  if (FLAG_dump_tables) {
    Symbols::DumpTable(I);
    DumpTypeTable(I);
    DumpTypeArgumentsTable(I);
  }

  TIMELINE_DURATION(T, Isolate, "WriteAppJITSnapshot");
  BlobImageWriter isolate_image_writer(T, isolate_snapshot_instructions_buffer,
                                       ApiReallocate,
                                       2 * MB /* initial_size */);
  FullSnapshotWriter writer(Snapshot::kFullJIT, NULL,
                            isolate_snapshot_data_buffer, ApiReallocate, NULL,
                            &isolate_image_writer);
  writer.WriteFullSnapshot();

  *isolate_snapshot_data_size = writer.IsolateSnapshotSize();
  *isolate_snapshot_instructions_size =
      isolate_image_writer.InstructionsBlobSize();

  return Api::Success();
#endif
}

DART_EXPORT Dart_Handle Dart_GetObfuscationMap(uint8_t** buffer,
                                               intptr_t* buffer_length) {
#if defined(DART_PRECOMPILED_RUNTIME)
  return Api::NewError("No obfuscation map to save on an AOT runtime.");
#elif !defined(DART_PRECOMPILER)
  return Api::NewError("Obfuscation is only supported for AOT compiler.");
#else
  Thread* thread = Thread::Current();
  DARTSCOPE(thread);
  Isolate* isolate = thread->isolate();

  if (buffer == NULL) {
    RETURN_NULL_ERROR(buffer);
  }
  if (buffer_length == NULL) {
    RETURN_NULL_ERROR(buffer_length);
  }

  // Note: can't use JSONStream in PRODUCT builds.
  const intptr_t kInitialBufferSize = 1 * MB;
  TextBuffer text_buffer(kInitialBufferSize);

  text_buffer.AddChar('[');
  if (isolate->obfuscation_map() != NULL) {
    for (intptr_t i = 0; isolate->obfuscation_map()[i] != NULL; i++) {
      if (i > 0) {
        text_buffer.AddChar(',');
      }
      text_buffer.AddChar('"');
      text_buffer.AddEscapedString(isolate->obfuscation_map()[i]);
      text_buffer.AddChar('"');
    }
  }
  text_buffer.AddChar(']');

  *buffer_length = text_buffer.length();
  *reinterpret_cast<char**>(buffer) = text_buffer.Steal();
  return Api::Success();
#endif
}

DART_EXPORT bool Dart_IsPrecompiledRuntime() {
#if defined(DART_PRECOMPILED_RUNTIME)
  return true;
#else
  return false;
#endif
}

DART_EXPORT void Dart_DumpNativeStackTrace(void* context) {
#ifndef PRODUCT
  Profiler::DumpStackTrace(context);
#endif
}

DART_EXPORT void Dart_PrepareToAbort() {
  OS::PrepareToAbort();
}

}  // namespace dart
