// 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 <utility>

#include "vm/isolate.h"

#include "include/dart_api.h"
#include "include/dart_native_api.h"
#include "platform/assert.h"
#include "platform/atomic.h"
#include "platform/growable_array.h"
#include "platform/text_buffer.h"
#include "vm/canonical_tables.h"
#include "vm/class_finalizer.h"
#include "vm/code_observers.h"
#include "vm/compiler/jit/compiler.h"
#include "vm/dart_api_message.h"
#include "vm/dart_api_state.h"
#include "vm/dart_entry.h"
#include "vm/debugger.h"
#include "vm/deopt_instructions.h"
#include "vm/dispatch_table.h"
#include "vm/ffi_callback_metadata.h"
#include "vm/flags.h"
#include "vm/heap/heap.h"
#include "vm/heap/pointer_block.h"
#include "vm/heap/safepoint.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/log.h"
#include "vm/message_handler.h"
#include "vm/message_snapshot.h"
#include "vm/object.h"
#include "vm/object_id_ring.h"
#include "vm/object_store.h"
#include "vm/os_thread.h"
#include "vm/port.h"
#include "vm/profiler.h"
#include "vm/reusable_handles.h"
#include "vm/reverse_pc_lookup_cache.h"
#include "vm/service.h"
#include "vm/service_event.h"
#include "vm/service_isolate.h"
#include "vm/simulator.h"
#include "vm/stack_frame.h"
#include "vm/stub_code.h"
#include "vm/symbols.h"
#include "vm/tags.h"
#include "vm/thread.h"
#include "vm/thread_interrupter.h"
#include "vm/thread_registry.h"
#include "vm/timeline.h"
#include "vm/visitor.h"

#if !defined(DART_PRECOMPILED_RUNTIME)
#include "vm/compiler/assembler/assembler.h"
#include "vm/compiler/stub_code_compiler.h"
#endif

namespace dart {

DECLARE_FLAG(bool, print_metrics);
DECLARE_FLAG(bool, trace_service);
DECLARE_FLAG(bool, trace_shutdown);
DECLARE_FLAG(bool, warn_on_pause_with_no_debugger);
DECLARE_FLAG(int, old_gen_growth_time_ratio);

// Reload flags.
DECLARE_FLAG(int, reload_every);
#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
DECLARE_FLAG(bool, check_reloaded);
DECLARE_FLAG(bool, reload_every_back_off);
DECLARE_FLAG(bool, trace_reload);
#endif  // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)

static void DeterministicModeHandler(bool value) {
  if (value) {
    FLAG_background_compilation = false;  // Timing dependent.
    FLAG_concurrent_mark = false;         // Timing dependent.
    FLAG_concurrent_sweep = false;        // Timing dependent.
    FLAG_scavenger_tasks = 0;             // Timing dependent.
    FLAG_old_gen_growth_time_ratio = 0;   // Timing dependent.
    FLAG_random_seed = 0x44617274;        // "Dart"
  }
}

DEFINE_FLAG_HANDLER(DeterministicModeHandler,
                    deterministic,
                    "Enable deterministic mode.");

DEFINE_FLAG(bool,
            disable_thread_pool_limit,
            false,
            "Disables the limit of the thread pool (simulates custom embedder "
            "with custom message handler on unlimited number of threads).");

// Quick access to the locally defined thread() and isolate() methods.
#define T (thread())
#define I (isolate())
#define IG (isolate_group())

#if defined(DEBUG)
// Helper class to ensure that a live origin_id is never reused
// and assigned to an isolate.
class VerifyOriginId : public IsolateVisitor {
 public:
  explicit VerifyOriginId(Dart_Port id) : id_(id) {}

  void VisitIsolate(Isolate* isolate) { ASSERT(isolate->origin_id() != id_); }

 private:
  Dart_Port id_;
  DISALLOW_COPY_AND_ASSIGN(VerifyOriginId);
};
#endif

static std::unique_ptr<Message> SerializeMessage(Dart_Port dest_port,
                                                 const Instance& obj) {
  return WriteMessage(/* same_group */ false, obj, dest_port,
                      Message::kNormalPriority);
}

static std::unique_ptr<Message> SerializeMessage(Zone* zone,
                                                 Dart_Port dest_port,
                                                 Dart_CObject* obj) {
  return WriteApiMessage(zone, obj, dest_port, Message::kNormalPriority);
}

void IsolateGroupSource::add_loaded_blob(
    Zone* zone,
    const ExternalTypedData& external_typed_data) {
  Array& loaded_blobs = Array::Handle();
  bool saved_external_typed_data = false;
  if (loaded_blobs_ != nullptr) {
    loaded_blobs = loaded_blobs_;

    // Walk the array, and (if stuff was removed) compact and reuse the space.
    // Note that the space has to be compacted as the ordering is important.
    WeakProperty& weak_property = WeakProperty::Handle();
    WeakProperty& weak_property_tmp = WeakProperty::Handle();
    ExternalTypedData& existing_entry = ExternalTypedData::Handle(zone);
    intptr_t next_entry_index = 0;
    for (intptr_t i = 0; i < loaded_blobs.Length(); i++) {
      weak_property ^= loaded_blobs.At(i);
      if (weak_property.key() != ExternalTypedData::null()) {
        if (i != next_entry_index) {
          existing_entry = ExternalTypedData::RawCast(weak_property.key());
          weak_property_tmp ^= loaded_blobs.At(next_entry_index);
          weak_property_tmp.set_key(existing_entry);
        }
        next_entry_index++;
      }
    }
    if (next_entry_index < loaded_blobs.Length()) {
      // There's now space to re-use.
      weak_property ^= loaded_blobs.At(next_entry_index);
      weak_property.set_key(external_typed_data);
      next_entry_index++;
      saved_external_typed_data = true;
    }
    if (next_entry_index < loaded_blobs.Length()) {
      ExternalTypedData& nullExternalTypedData =
          ExternalTypedData::Handle(zone);
      while (next_entry_index < loaded_blobs.Length()) {
        // Null out any extra spaces.
        weak_property ^= loaded_blobs.At(next_entry_index);
        weak_property.set_key(nullExternalTypedData);
        next_entry_index++;
      }
    }
  }
  if (!saved_external_typed_data) {
    const WeakProperty& weak_property =
        WeakProperty::Handle(WeakProperty::New(Heap::kOld));
    weak_property.set_key(external_typed_data);

    intptr_t length = loaded_blobs.IsNull() ? 0 : loaded_blobs.Length();
    Array& new_array =
        Array::Handle(Array::Grow(loaded_blobs, length + 1, Heap::kOld));
    new_array.SetAt(length, weak_property);
    loaded_blobs_ = new_array.ptr();
  }
  num_blob_loads_++;
}

void IdleTimeHandler::InitializeWithHeap(Heap* heap) {
  MutexLocker ml(&mutex_);
  ASSERT(heap_ == nullptr && heap != nullptr);
  heap_ = heap;
}

bool IdleTimeHandler::ShouldCheckForIdle() {
  MutexLocker ml(&mutex_);
  return idle_start_time_ > 0 && FLAG_idle_timeout_micros != 0 &&
         disabled_counter_ == 0;
}

void IdleTimeHandler::UpdateStartIdleTime() {
  MutexLocker ml(&mutex_);
  if (disabled_counter_ == 0) {
    idle_start_time_ = OS::GetCurrentMonotonicMicros();
  }
}

bool IdleTimeHandler::ShouldNotifyIdle(int64_t* expiry) {
  const int64_t now = OS::GetCurrentMonotonicMicros();

  MutexLocker ml(&mutex_);
  if (idle_start_time_ > 0 && disabled_counter_ == 0) {
    const int64_t expiry_time = idle_start_time_ + FLAG_idle_timeout_micros;
    if (expiry_time < now) {
      idle_start_time_ = 0;
      return true;
    }
  }

  *expiry = now + FLAG_idle_timeout_micros;
  return false;
}

void IdleTimeHandler::NotifyIdle(int64_t deadline) {
  {
    MutexLocker ml(&mutex_);
    disabled_counter_++;
  }
  if (heap_ != nullptr) {
    heap_->NotifyIdle(deadline);
  }
  {
    MutexLocker ml(&mutex_);
    disabled_counter_--;
    idle_start_time_ = 0;
  }
}

void IdleTimeHandler::NotifyIdleUsingDefaultDeadline() {
  const int64_t now = OS::GetCurrentMonotonicMicros();
  NotifyIdle(now + FLAG_idle_duration_micros);
}

DisableIdleTimerScope::DisableIdleTimerScope(IdleTimeHandler* handler)
    : handler_(handler) {
  if (handler_ != nullptr) {
    MutexLocker ml(&handler_->mutex_);
    ++handler_->disabled_counter_;
    handler_->idle_start_time_ = 0;
  }
}

DisableIdleTimerScope::~DisableIdleTimerScope() {
  if (handler_ != nullptr) {
    MutexLocker ml(&handler_->mutex_);
    --handler_->disabled_counter_;
    ASSERT(handler_->disabled_counter_ >= 0);
  }
}

class FinalizeWeakPersistentHandlesVisitor : public HandleVisitor {
 public:
  explicit FinalizeWeakPersistentHandlesVisitor(IsolateGroup* isolate_group)
      : HandleVisitor(Thread::Current()), isolate_group_(isolate_group) {}

  void VisitHandle(uword addr) override {
    auto handle = reinterpret_cast<FinalizablePersistentHandle*>(addr);
    handle->UpdateUnreachable(isolate_group_);
  }

 private:
  IsolateGroup* isolate_group_;

  DISALLOW_COPY_AND_ASSIGN(FinalizeWeakPersistentHandlesVisitor);
};

void MutatorThreadPool::OnEnterIdleLocked(MutexLocker* ml, Worker* worker) {
  if (FLAG_idle_timeout_micros == 0) return;

  // If the isolate has not started running application code yet, we ignore the
  // idle time.
  if (!isolate_group_->initial_spawn_successful()) return;

  int64_t idle_expiry = 0;
  // Obtain the idle time we should wait.
  if (isolate_group_->idle_time_handler()->ShouldNotifyIdle(&idle_expiry)) {
    MutexUnlocker mls(ml);
    NotifyIdle();
    return;
  }

  // Avoid shutdown having to wait for the timeout to expire.
  if (ShuttingDownLocked()) return;

  // Wait for the recommended idle timeout.
  // We can be woken up because of a), b) or c)
  const auto result =
      worker->Sleep(idle_expiry - OS::GetCurrentMonotonicMicros());

  // a) If there are new tasks we have to run them.
  if (TasksWaitingToRunLocked()) return;

  // b) If the thread pool is shutting down we're done.
  if (ShuttingDownLocked()) return;

  // c) We timed out and should run the idle notifier.
  if (result == Monitor::kTimedOut &&
      isolate_group_->idle_time_handler()->ShouldNotifyIdle(&idle_expiry)) {
    MutexUnlocker mls(ml);
    NotifyIdle();
    return;
  }

  // There must've been another thread doing active work in the meantime.
  // If that thread becomes idle and is the last idle thread it will run this
  // code again.
}

void MutatorThreadPool::NotifyIdle() {
  EnterIsolateGroupScope isolate_group_scope(isolate_group_);
  isolate_group_->idle_time_handler()->NotifyIdleUsingDefaultDeadline();
}

IsolateGroup::IsolateGroup(std::shared_ptr<IsolateGroupSource> source,
                           void* embedder_data,
                           ObjectStore* object_store,
                           Dart_IsolateFlags api_flags,
                           bool is_vm_isolate)
    : class_table_(nullptr),
      cached_class_table_table_(nullptr),
      object_store_(object_store),
      class_table_allocator_(),
      is_vm_isolate_(is_vm_isolate),
      embedder_data_(embedder_data),
      thread_pool_(),
      isolates_lock_(new SafepointRwLock()),
      isolates_(),
      start_time_micros_(OS::GetCurrentMonotonicMicros()),
      is_system_isolate_group_(source->flags.is_system_isolate),
      random_(),
#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
      last_reload_timestamp_(OS::GetCurrentTimeMillis()),
      reload_every_n_stack_overflow_checks_(FLAG_reload_every),
#endif
      source_(std::move(source)),
      api_state_(new ApiState()),
      thread_registry_(new ThreadRegistry()),
      safepoint_handler_(new SafepointHandler(this)),
      store_buffer_(new StoreBuffer()),
      heap_(nullptr),
      saved_unlinked_calls_(Array::null()),
      initial_field_table_(new FieldTable(/*isolate=*/nullptr)),
      shared_initial_field_table_(new FieldTable(/*isolate=*/nullptr,
                                                 /*isolate_group=*/nullptr)),
      shared_field_table_(new FieldTable(/*isolate=*/nullptr, this)),
#if !defined(DART_PRECOMPILED_RUNTIME)
      background_compiler_(new BackgroundCompiler(this)),
#endif
      symbols_mutex_(),
      type_canonicalization_mutex_(),
      type_arguments_canonicalization_mutex_(),
      subtype_test_cache_mutex_(),
      megamorphic_table_mutex_(),
      type_feedback_mutex_(),
      patchable_call_mutex_(),
      constant_canonicalization_mutex_(),
      kernel_data_lib_cache_mutex_(),
      kernel_data_class_cache_mutex_(),
      kernel_constants_mutex_(),
      field_list_mutex_(),
      boxed_field_list_(GrowableObjectArray::null()),
      program_lock_(new SafepointRwLock(SafepointLevel::kGCAndDeopt)),
      active_mutators_monitor_(new Monitor()),
      max_active_mutators_(Scavenger::MaxMutatorThreadCount())
#if !defined(PRODUCT)
      ,
      debugger_(new GroupDebugger(this))
#endif
{
  FlagsCopyFrom(api_flags);
  if (!is_vm_isolate) {
    thread_pool_.reset(
        new MutatorThreadPool(this, FLAG_disable_thread_pool_limit
                                        ? 0
                                        : Scavenger::MaxMutatorThreadCount()));
  }
  {
    WriteRwLocker wl(ThreadState::Current(), isolate_groups_rwlock_);
    // Keep isolate IDs less than 2^53 so web clients of the service
    // protocol can process it properly.
    //
    // See https://github.com/dart-lang/sdk/issues/53081.
    id_ = isolate_group_random_->NextJSInt();
  }
  heap_walk_class_table_ = class_table_ =
      new ClassTable(&class_table_allocator_);
  cached_class_table_table_.store(class_table_->table());
  memset(&native_assets_api_, 0, sizeof(NativeAssetsApi));
}

IsolateGroup::IsolateGroup(std::shared_ptr<IsolateGroupSource> source,
                           void* embedder_data,
                           Dart_IsolateFlags api_flags,
                           bool is_vm_isolate)
    : IsolateGroup(source,
                   embedder_data,
                   new ObjectStore(),
                   api_flags,
                   is_vm_isolate) {
  if (object_store() != nullptr) {
    object_store()->InitStubs();
  }
}

IsolateGroup::~IsolateGroup() {
  // Ensure we destroy the heap before the other members.
  heap_ = nullptr;
  ASSERT(old_marking_stack_ == nullptr);
  ASSERT(new_marking_stack_ == nullptr);
  ASSERT(deferred_marking_stack_ == nullptr);

  if (obfuscation_map_ != nullptr) {
    for (intptr_t i = 0; obfuscation_map_[i] != nullptr; i++) {
      delete[] obfuscation_map_[i];
    }
    delete[] obfuscation_map_;
  }

  class_table_allocator_.Free(class_table_);
  if (heap_walk_class_table_ != class_table_) {
    class_table_allocator_.Free(heap_walk_class_table_);
  }

#if !defined(PRODUCT)
  delete debugger_;
  debugger_ = nullptr;
#endif
}

void IsolateGroup::RegisterIsolate(Isolate* isolate) {
  SafepointWriteRwLocker ml(Thread::Current(), isolates_lock_.get());
  ASSERT(isolates_lock_->IsCurrentThreadWriter());
  isolates_.Append(isolate);
  isolate_count_++;
}

bool IsolateGroup::ContainsOnlyOneIsolate() {
  SafepointReadRwLocker ml(Thread::Current(), isolates_lock_.get());
  // We do allow 0 here as well, because the background compiler might call
  // this method while the mutator thread is in shutdown procedure and
  // unregistered itself already.
  return isolate_count_ == 0 || isolate_count_ == 1;
}

void IsolateGroup::RunWithLockedGroup(std::function<void()> fun) {
  SafepointWriteRwLocker ml(Thread::Current(), isolates_lock_.get());
  fun();
}

void IsolateGroup::UnregisterIsolate(Isolate* isolate) {
  SafepointWriteRwLocker ml(Thread::Current(), isolates_lock_.get());
  isolates_.Remove(isolate);
}

bool IsolateGroup::UnregisterIsolateDecrementCount() {
  SafepointWriteRwLocker ml(Thread::Current(), isolates_lock_.get());
  isolate_count_--;
  return isolate_count_ == 0;
}

void IsolateGroup::CreateHeap(bool is_vm_isolate,
                              bool is_service_or_kernel_isolate) {
  Heap::Init(this, is_vm_isolate,
             is_vm_isolate
                 ? 0  // New gen size 0; VM isolate should only allocate in old.
                 : FLAG_new_gen_semi_max_size * MBInWords,
             (is_service_or_kernel_isolate ? kDefaultMaxOldGenHeapSize
                                           : FLAG_old_gen_heap_size) *
                 MBInWords);

#define ISOLATE_GROUP_METRIC_CONSTRUCTORS(type, variable, name, unit)          \
  metric_##variable##_.InitInstance(this, name, nullptr, Metric::unit);
  ISOLATE_GROUP_METRIC_LIST(ISOLATE_GROUP_METRIC_CONSTRUCTORS)
#undef ISOLATE_GROUP_METRIC_CONSTRUCTORS
}

void IsolateGroup::Shutdown() {
  char* name = nullptr;
  // We retrieve the flag value once to avoid the compiler complaining about the
  // possibly uninitialized value of name, as the compiler is unaware that when
  // the flag variable is non-const, it is set once during VM initialization and
  // never changed after, and that modification never runs concurrently with
  // this method.
  const bool trace_shutdown = FLAG_trace_shutdown;

  if (trace_shutdown) {
    name = Utils::StrDup(source()->name);
    OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Shutdown starting for group %s\n",
                 Dart::UptimeMillis(), name);
  }
  // Ensure to join all threads before waiting for pending GC tasks (the thread
  // pool can trigger idle notification, which can start new GC tasks).
  //
  // (The vm-isolate doesn't have a thread pool.)
  if (!is_vm_isolate_) {
    ASSERT(thread_pool_ != nullptr);
    thread_pool_->Shutdown();
    thread_pool_.reset();
  }

  // Needs to happen before starting to destroy the heap so helper tasks like
  // the SampleBlockProcessor don't try to enter the group during this
  // tear-down.
  UnregisterIsolateGroup(this);

  // Wait for any pending GC tasks.
  if (heap_ != nullptr) {
    // Wait for any concurrent GC tasks to finish before shutting down.
    // TODO(rmacnak): Interrupt tasks for faster shutdown.
    PageSpace* old_space = heap_->old_space();
    MonitorLocker ml(old_space->tasks_lock());
    while (old_space->tasks() > 0) {
      ml.Wait();
    }
    // Needs to happen before ~PageSpace so TLS and the thread registry are
    // still valid.
    old_space->AbandonMarkingForShutdown();
  }

  // If the creation of the isolate group (or the first isolate within the
  // isolate group) failed, we do not invoke the cleanup callback (the
  // embedder is responsible for handling the creation error).
  if (initial_spawn_successful_ && !is_vm_isolate_) {
    auto group_shutdown_callback = Isolate::GroupCleanupCallback();
    if (group_shutdown_callback != nullptr) {
      group_shutdown_callback(embedder_data());
    }
  }

  delete this;

  // After this isolate group has died we might need to notify a pending
  // `Dart_Cleanup()` call.
  {
    if (trace_shutdown) {
      OS::PrintErr("[+%" Pd64
                   "ms] SHUTDOWN: Notifying "
                   "isolate group shutdown (%s)\n",
                   Dart::UptimeMillis(), name);
    }
    MonitorLocker ml(Isolate::isolate_creation_monitor_);
    if (!Isolate::creation_enabled_ &&
        !IsolateGroup::HasApplicationIsolateGroups()) {
      ml.Notify();
    }
    if (trace_shutdown) {
      OS::PrintErr("[+%" Pd64
                   "ms] SHUTDOWN: Done Notifying "
                   "isolate group shutdown (%s)\n",
                   Dart::UptimeMillis(), name);
    }
  }
  if (trace_shutdown) {
    OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Done shutdown for group %s\n",
                 Dart::UptimeMillis(), name);
    free(name);
  }
}

void IsolateGroup::set_heap(std::unique_ptr<Heap> heap) {
  idle_time_handler_.InitializeWithHeap(heap.get());
  heap_ = std::move(heap);
}

void IsolateGroup::set_saved_unlinked_calls(const Array& saved_unlinked_calls) {
  saved_unlinked_calls_ = saved_unlinked_calls.ptr();
}

void IsolateGroup::IncreaseMutatorCount(Isolate* mutator,
                                        bool is_nested_reenter) {
  ASSERT(mutator->group() == this);

  // If the mutator was temporarily blocked on a worker thread, we have to
  // unblock the worker thread again.
  if (is_nested_reenter) {
    ASSERT(mutator->mutator_thread() != nullptr);
    thread_pool()->MarkCurrentWorkerAsUnBlocked();
  }

  // Prevent too many mutators from entering the isolate group to avoid
  // pathological behavior where many threads are fighting for obtaining TLABs.
  {
    // NOTE: This is performance critical code, we should avoid monitors and use
    // std::atomics in the fast case (where active_mutators <
    // max_active_mutators) and only use monitors in the uncommon case.
    MonitorLocker ml(active_mutators_monitor_.get());
    ASSERT(active_mutators_ <= max_active_mutators_);
    while (active_mutators_ == max_active_mutators_) {
      waiting_mutators_++;
      ml.Wait();
      waiting_mutators_--;
    }
    active_mutators_++;
  }
}

void IsolateGroup::DecreaseMutatorCount(Isolate* mutator, bool is_nested_exit) {
  ASSERT(mutator->group() == this);

  // If the mutator thread has an active stack and runs on our thread pool we
  // will mark the worker as blocked, thereby possibly spawning a new worker for
  // pending tasks (if there are any).
  if (is_nested_exit) {
    ASSERT(mutator->mutator_thread() != nullptr);
    thread_pool()->MarkCurrentWorkerAsBlocked();
  }

  {
    // NOTE: This is performance critical code, we should avoid monitors and use
    // std::atomics in the fast case (where active_mutators <
    // max_active_mutators) and only use monitors in the uncommon case.
    MonitorLocker ml(active_mutators_monitor_.get());
    ASSERT(active_mutators_ <= max_active_mutators_);
    active_mutators_--;
    if (waiting_mutators_ > 0) {
      ml.Notify();
    }
  }
}

#ifndef PRODUCT
void IsolateGroup::PrintJSON(JSONStream* stream, bool ref) {
  JSONObject jsobj(stream);
  PrintToJSONObject(&jsobj, ref);
}

void IsolateGroup::PrintToJSONObject(JSONObject* jsobj, bool ref) {
  jsobj->AddProperty("type", (ref ? "@IsolateGroup" : "IsolateGroup"));
  jsobj->AddServiceId(ISOLATE_GROUP_SERVICE_ID_FORMAT_STRING, id());

  jsobj->AddProperty("name", source()->script_uri);
  jsobj->AddPropertyF("number", "%" Pu64 "", id());
  jsobj->AddProperty("isSystemIsolateGroup", is_system_isolate_group());
  if (ref) {
    return;
  }

  {
    JSONArray isolate_array(jsobj, "isolates");
    for (auto it = isolates_.Begin(); it != isolates_.End(); ++it) {
      Isolate* isolate = *it;
      isolate_array.AddValue(isolate, /*ref=*/true);
    }
  }
}

void IsolateGroup::PrintMemoryUsageJSON(JSONStream* stream) {
  int64_t used = heap()->TotalUsedInWords();
  int64_t capacity = heap()->TotalCapacityInWords();
  int64_t external_used = heap()->TotalExternalInWords();

  JSONObject jsobj(stream);
  // This is the same "MemoryUsage" that the isolate-specific "getMemoryUsage"
  // rpc method returns.
  jsobj.AddProperty("type", "MemoryUsage");
  jsobj.AddProperty64("heapUsage", used * kWordSize);
  jsobj.AddProperty64("heapCapacity", capacity * kWordSize);
  jsobj.AddProperty64("externalUsage", external_used * kWordSize);
}
#endif

void IsolateGroup::ForEach(std::function<void(IsolateGroup*)> action) {
  ReadRwLocker wl(Thread::Current(), isolate_groups_rwlock_);
  for (auto isolate_group : *isolate_groups_) {
    action(isolate_group);
  }
}

void IsolateGroup::RunWithIsolateGroup(
    uint64_t id,
    std::function<void(IsolateGroup*)> action,
    std::function<void()> not_found) {
  ReadRwLocker wl(Thread::Current(), isolate_groups_rwlock_);
  for (auto isolate_group : *isolate_groups_) {
    if (isolate_group->id() == id) {
      action(isolate_group);
      return;
    }
  }
  not_found();
}

void IsolateGroup::RegisterIsolateGroup(IsolateGroup* isolate_group) {
  WriteRwLocker wl(ThreadState::Current(), isolate_groups_rwlock_);
  isolate_groups_->Append(isolate_group);
}

void IsolateGroup::UnregisterIsolateGroup(IsolateGroup* isolate_group) {
  WriteRwLocker wl(ThreadState::Current(), isolate_groups_rwlock_);
  isolate_groups_->Remove(isolate_group);
}

bool IsolateGroup::HasApplicationIsolateGroups() {
  ReadRwLocker wl(ThreadState::Current(), isolate_groups_rwlock_);
  for (auto group : *isolate_groups_) {
    if (!IsolateGroup::IsSystemIsolateGroup(group)) {
      return true;
    }
  }
  return false;
}

bool IsolateGroup::HasOnlyVMIsolateGroup() {
  ReadRwLocker wl(ThreadState::Current(), isolate_groups_rwlock_);
  for (auto group : *isolate_groups_) {
    if (!group->is_vm_isolate()) {
      return false;
    }
  }
  return true;
}

void IsolateGroup::Init() {
  ASSERT(isolate_groups_rwlock_ == nullptr);
  isolate_groups_rwlock_ = new RwLock();
  ASSERT(isolate_groups_ == nullptr);
  isolate_groups_ = new IntrusiveDList<IsolateGroup>();
  isolate_group_random_ = new Random();
}

void IsolateGroup::Cleanup() {
  delete isolate_group_random_;
  isolate_group_random_ = nullptr;
  delete isolate_groups_rwlock_;
  isolate_groups_rwlock_ = nullptr;
  ASSERT(isolate_groups_->IsEmpty());
  delete isolate_groups_;
  isolate_groups_ = nullptr;
}

bool IsolateVisitor::IsSystemIsolate(Isolate* isolate) const {
  return Isolate::IsSystemIsolate(isolate);
}

Bequest::~Bequest() {
  if (handle_ == nullptr) {
    return;
  }

  IsolateGroup* isolate_group = IsolateGroup::Current();
  CHECK_ISOLATE_GROUP(isolate_group);
  NoSafepointScope no_safepoint_scope;
  ApiState* state = isolate_group->api_state();
  ASSERT(state != nullptr);
  state->FreePersistentHandle(handle_);
}

void IsolateGroup::RegisterClass(const Class& cls) {
#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
  if (IsReloading()) {
    program_reload_context()->RegisterClass(cls);
    return;
  }
#endif  // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
  if (cls.IsTopLevel()) {
    class_table()->RegisterTopLevel(cls);
  } else {
    class_table()->Register(cls);
  }
}

#if defined(DEBUG)
void IsolateGroup::ValidateClassTable() {
  class_table()->Validate();
}
#endif  // DEBUG

void IsolateGroup::RegisterSharedStaticField(const Field& field,
                                             const Object& initial_value) {
  const bool need_to_grow_backing_store =
      shared_initial_field_table()->Register(field);
  const intptr_t field_id = field.field_id();
  shared_initial_field_table()->SetAt(field_id, initial_value.ptr());

  if (need_to_grow_backing_store) {
    // We have to stop other isolates from accessing shared isolate group
    // field state, since we'll have to grow the backing store.
    GcSafepointOperationScope scope(Thread::Current());
    const bool need_to_grow_other_backing_store =
        shared_field_table()->Register(field, field_id);
    ASSERT(need_to_grow_other_backing_store);
  } else {
    const bool need_to_grow_other_backing_store =
        shared_field_table()->Register(field, field_id);
    ASSERT(!need_to_grow_other_backing_store);
  }
  shared_field_table()->SetAt(field_id, initial_value.ptr());
}

void IsolateGroup::RegisterStaticField(const Field& field,
                                       const Object& initial_value) {
  ASSERT(program_lock()->IsCurrentThreadWriter());

  ASSERT(field.is_static());
  if (field.is_shared()) {
    RegisterSharedStaticField(field, initial_value);
    return;
  }
  const bool need_to_grow_backing_store =
      initial_field_table()->Register(field);
  const intptr_t field_id = field.field_id();
  initial_field_table()->SetAt(field_id, initial_value.ptr());

  SafepointReadRwLocker ml(Thread::Current(), isolates_lock_.get());
  if (need_to_grow_backing_store) {
    // We have to stop other isolates from accessing their field state, since
    // we'll have to grow the backing store.
    GcSafepointOperationScope scope(Thread::Current());
    for (auto isolate : isolates_) {
      auto field_table = isolate->field_table();
      if (field_table->IsReadyToUse()) {
        field_table->Register(field, field_id);
        field_table->SetAt(field_id, initial_value.ptr());
      }
    }
  } else {
    for (auto isolate : isolates_) {
      auto field_table = isolate->field_table();
      if (field_table->IsReadyToUse()) {
        field_table->Register(field, field_id);
        field_table->SetAt(field_id, initial_value.ptr());
      }
    }
  }
}

void IsolateGroup::FreeStaticField(const Field& field) {
#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
  // This can only be called during hot-reload.
  ASSERT(program_reload_context() != nullptr);
#endif

  const intptr_t field_id = field.field_id();
  if (field.is_shared()) {
    shared_field_table()->Free(field_id);
  } else {
    initial_field_table()->Free(field_id);
    ForEachIsolate([&](Isolate* isolate) {
      auto field_table = isolate->field_table();
      // The isolate might've just been created and is now participating in
      // the reload request inside `IsolateGroup::RegisterIsolate()`.
      // At that point it doesn't have the field table setup yet.
      if (field_table->IsReadyToUse()) {
        field_table->Free(field_id);
      }
    });
  }
}

Isolate* IsolateGroup::EnterTemporaryIsolate() {
  Dart_IsolateFlags flags;
  Isolate::FlagsInitialize(&flags);
  Isolate* const isolate = Isolate::InitIsolate("temp", this, flags);
  ASSERT(isolate != nullptr);
  ASSERT(Isolate::Current() == isolate);
  return isolate;
}

void IsolateGroup::ExitTemporaryIsolate() {
  Thread* thread = Thread::Current();
  ASSERT(thread != nullptr);
  thread->set_execution_state(Thread::kThreadInVM);
  Dart::ShutdownIsolate(thread);
}

void IsolateGroup::RehashConstants(Become* become) {
  // Even though no individual constant contains a cycle, there can be "cycles"
  // between the canonical tables if some const instances of A have fields that
  // are const instance of B and vice versa. So set all the old tables to the
  // side and clear all the tables attached to the classes before rehashing
  // instead of resetting and rehash one class at a time.

  Thread* thread = Thread::Current();
  StackZone stack_zone(thread);
  Zone* zone = stack_zone.GetZone();

  intptr_t num_cids = class_table()->NumCids();
  Array** old_constant_tables = zone->Alloc<Array*>(num_cids);
  for (intptr_t i = 0; i < num_cids; i++) {
    old_constant_tables[i] = nullptr;
  }

  Class& cls = Class::Handle(zone);
  for (intptr_t cid = kInstanceCid; cid < num_cids; cid++) {
    if (!class_table()->IsValidIndex(cid) ||
        !class_table()->HasValidClassAt(cid)) {
      continue;
    }
    if ((cid == kTypeArgumentsCid) || IsStringClassId(cid)) {
      // TypeArguments and Symbols have special tables for canonical objects
      // that aren't based on address.
      continue;
    }
    if ((cid == kMintCid) || (cid == kDoubleCid)) {
      // Constants stored as a plain list or in a hashset with a stable
      // hashcode, which only depends on the actual value of the constant.
      continue;
    }

    cls = class_table()->At(cid);
    if (cls.constants() == Array::null()) continue;
    old_constant_tables[cid] = &Array::Handle(zone, cls.constants());
    cls.set_constants(Object::null_array());
  }

  // Clear invalid hashes.
  heap()->ResetCanonicalHashTable();

  Instance& constant = Instance::Handle(zone);
  Field& field = Field::Handle(zone);
  String& name = String::Handle(zone);
  Array& new_values = Array::Handle(zone);
  Instance& old_value = Instance::Handle(zone);
  Instance& new_value = Instance::Handle(zone);
  Instance& deleted = Instance::Handle(zone);

  if (become != nullptr) {
    for (intptr_t cid = kInstanceCid; cid < num_cids; cid++) {
      Array* old_constants = old_constant_tables[cid];
      if (old_constants == nullptr) continue;

      cls = class_table()->At(cid);
      CanonicalInstancesSet set(zone, old_constants->ptr());
      CanonicalInstancesSet::Iterator it(&set);
      while (it.MoveNext()) {
        constant ^= set.GetKey(it.Current());
        ASSERT(!constant.IsNull());
        ASSERT(!constant.InVMIsolateHeap());
        constant.ClearCanonical();
      }
      set.Release();
    }
  }

  for (intptr_t cid = kInstanceCid; cid < num_cids; cid++) {
    Array* old_constants = old_constant_tables[cid];
    if (old_constants == nullptr) continue;

    cls = class_table()->At(cid);
    CanonicalInstancesSet set(zone, old_constants->ptr());
    CanonicalInstancesSet::Iterator it(&set);

    if (cls.is_enum_class() && (become != nullptr)) {
      field = cls.LookupStaticField(Symbols::_DeletedEnumSentinel());
      deleted ^= field.StaticConstFieldValue();
      if (deleted.IsNull()) {
        deleted = Instance::New(cls, Heap::kOld);
        field = object_store()->enum_name_field();
        name = cls.ScrubbedName();
        name = Symbols::FromConcat(thread, Symbols::_DeletedEnumPrefix(), name);
        deleted.SetField(field, name);
        field = object_store()->enum_index_field();
        new_value = Smi::New(-1);
        deleted.SetField(field, new_value);
        field = cls.LookupStaticField(Symbols::_DeletedEnumSentinel());
        // The static const field contains `Object::null()` instead of
        // `Object::sentinel()` - so it's not considered an initializing store.
        field.SetStaticConstFieldValue(deleted,
                                       /*assert_initializing_store*/ false);
      }

      field = cls.LookupField(Symbols::Values());
      new_values ^= field.StaticConstFieldValue();

      field = object_store()->enum_name_field();
      while (it.MoveNext()) {
        old_value ^= set.GetKey(it.Current());
        ASSERT(old_value.GetClassId() == cid);
        bool found = false;
        for (intptr_t j = 0; j < new_values.Length(); j++) {
          new_value ^= new_values.At(j);
          ASSERT(new_value.GetClassId() == cid);
          if (old_value.GetField(field) == new_value.GetField(field)) {
            found = true;
            break;
          }
        }
        if (!found) {
          new_value = deleted.ptr();
        }

        if (old_value.ptr() != new_value.ptr()) {
          become->Add(old_value, new_value, "enum forwarding");
        }
        if (new_value.IsCanonical()) {
          cls.InsertCanonicalConstant(zone, new_value);
        }
      }
    } else {
      while (it.MoveNext()) {
        old_value ^= set.GetKey(it.Current());
        ASSERT(!old_value.IsNull());

        if (become == nullptr) {
          ASSERT(old_value.IsCanonical());
          cls.InsertCanonicalConstant(zone, old_value);
        } else {
          new_value = old_value.Canonicalize(thread);
          if (old_value.ptr() != new_value.ptr()) {
            become->Add(old_value, new_value, "constant forwarding");
          }
        }
      }
    }
    set.Release();
  }

  // Save memory.
  heap()->ResetCanonicalHashTable();
}

void Isolate::SendInternalLibMessage(LibMsgId msg_id, uint64_t capability) {
  const bool ok = SendInternalLibMessage(main_port(), msg_id, capability);
  if (!ok) UNREACHABLE();
}

bool Isolate::SendInternalLibMessage(Dart_Port main_port,
                                     LibMsgId msg_id,
                                     uint64_t capability) {
  Dart_CObject array_entry_msg_kind;
  array_entry_msg_kind.type = Dart_CObject_kInt64;
  array_entry_msg_kind.value.as_int64 = Message::kIsolateLibOOBMsg;

  Dart_CObject array_entry_msg_id;
  array_entry_msg_id.type = Dart_CObject_kInt64;
  array_entry_msg_id.value.as_int64 = msg_id;

  Dart_CObject array_entry_capability;
  array_entry_capability.type = Dart_CObject_kCapability;
  array_entry_capability.value.as_capability.id = capability;

  Dart_CObject* array_entries[3] = {
      &array_entry_msg_kind,
      &array_entry_msg_id,
      &array_entry_capability,
  };

  Dart_CObject message;
  message.type = Dart_CObject_kArray;
  message.value.as_array.values = array_entries;
  message.value.as_array.length = ARRAY_SIZE(array_entries);

  AllocOnlyStackZone zone;
  std::unique_ptr<Message> msg = WriteApiMessage(
      zone.GetZone(), &message, main_port, Message::kOOBPriority);
  if (msg == nullptr) UNREACHABLE();

  return PortMap::PostMessage(std::move(msg));
}

void IsolateGroup::set_object_store(ObjectStore* object_store) {
  object_store_.reset(object_store);
}

class IsolateMessageHandler : public MessageHandler {
 public:
  explicit IsolateMessageHandler(Isolate* isolate);
  ~IsolateMessageHandler();

  const char* name() const;
  void MessageNotify(Message::Priority priority);
  MessageStatus HandleMessage(std::unique_ptr<Message> message);
#ifndef PRODUCT
  void NotifyPauseOnStart();
  void NotifyPauseOnExit();
#endif  // !PRODUCT

#if defined(DEBUG)
  // Check that it is safe to access this handler.
  void CheckAccess() const;
#endif
  bool IsCurrentIsolate() const;
  virtual Isolate* isolate() const { return isolate_; }
  virtual IsolateGroup* isolate_group() const { return isolate_->group(); }

  virtual bool KeepAliveLocked() {
    // If the message handler was asked to shutdown we shut down.
    if (!MessageHandler::KeepAliveLocked()) return false;
    // Otherwise we only stay alive as long as there's active receive ports, or
    // there are FFI callbacks keeping the isolate alive.
    return isolate_->HasLivePorts() || isolate_->HasOpenNativeCallables();
  }

 private:
  // A result of false indicates that the isolate should terminate the
  // processing of further events.
  ErrorPtr HandleLibMessage(const Array& message);

  MessageStatus ProcessUnhandledException(const Error& result);
  Isolate* isolate_;
};

IsolateMessageHandler::IsolateMessageHandler(Isolate* isolate)
    : isolate_(isolate) {}

IsolateMessageHandler::~IsolateMessageHandler() {}

const char* IsolateMessageHandler::name() const {
  return isolate_->name();
}

// Isolate library OOB messages are fixed sized arrays which have the
// following format:
// [ OOB dispatch, Isolate library dispatch, <message specific data> ]
ErrorPtr IsolateMessageHandler::HandleLibMessage(const Array& message) {
  if (message.Length() < 2) return Error::null();
  Zone* zone = T->zone();
  const Object& type = Object::Handle(zone, message.At(1));
  if (!type.IsSmi()) return Error::null();
  const intptr_t msg_type = Smi::Cast(type).Value();
  switch (msg_type) {
    case Isolate::kPauseMsg: {
      // [ OOB, kPauseMsg, pause capability, resume capability ]
      if (message.Length() != 4) return Error::null();
      Object& obj = Object::Handle(zone, message.At(2));
      if (!I->VerifyPauseCapability(obj)) return Error::null();
      obj = message.At(3);
      if (!obj.IsCapability()) return Error::null();
      if (I->AddResumeCapability(Capability::Cast(obj))) {
        increment_paused();
      }
      break;
    }
    case Isolate::kResumeMsg: {
      // [ OOB, kResumeMsg, pause capability, resume capability ]
      if (message.Length() != 4) return Error::null();
      Object& obj = Object::Handle(zone, message.At(2));
      if (!I->VerifyPauseCapability(obj)) return Error::null();
      obj = message.At(3);
      if (!obj.IsCapability()) return Error::null();
      if (I->RemoveResumeCapability(Capability::Cast(obj))) {
        decrement_paused();
      }
      break;
    }
    case Isolate::kPingMsg: {
      // [ OOB, kPingMsg, responsePort, priority, response ]
      if (message.Length() != 5) return Error::null();
      const Object& obj2 = Object::Handle(zone, message.At(2));
      if (!obj2.IsSendPort()) return Error::null();
      const SendPort& send_port = SendPort::Cast(obj2);
      const Object& obj3 = Object::Handle(zone, message.At(3));
      if (!obj3.IsSmi()) return Error::null();
      const intptr_t priority = Smi::Cast(obj3).Value();
      const Object& obj4 = Object::Handle(zone, message.At(4));
      if (!obj4.IsInstance() && !obj4.IsNull()) return Error::null();
      const Instance& response =
          obj4.IsNull() ? Instance::null_instance() : Instance::Cast(obj4);
      if (priority == Isolate::kImmediateAction) {
        PortMap::PostMessage(SerializeMessage(send_port.Id(), response));
      } else {
        ASSERT((priority == Isolate::kBeforeNextEventAction) ||
               (priority == Isolate::kAsEventAction));
        // Update the message so that it will be handled immediately when it
        // is picked up from the message queue the next time.
        message.SetAt(
            0, Smi::Handle(zone, Smi::New(Message::kDelayedIsolateLibOOBMsg)));
        message.SetAt(3,
                      Smi::Handle(zone, Smi::New(Isolate::kImmediateAction)));
        this->PostMessage(
            SerializeMessage(Message::kIllegalPort, message),
            priority == Isolate::kBeforeNextEventAction /* at_head */);
      }
      break;
    }
    case Isolate::kKillMsg:
    case Isolate::kInternalKillMsg: {
      // [ OOB, kKillMsg, terminate capability, priority ]
      if (message.Length() != 4) return Error::null();
      Object& obj = Object::Handle(zone, message.At(3));
      if (!obj.IsSmi()) return Error::null();
      const intptr_t priority = Smi::Cast(obj).Value();
      if (priority == Isolate::kImmediateAction) {
        Thread::Current()->StartUnwindError();
        obj = message.At(2);
        if (I->VerifyTerminateCapability(obj)) {
          // We will kill the current isolate by returning an UnwindError.
          if (msg_type == Isolate::kKillMsg) {
            const String& msg = String::Handle(
                String::New("isolate terminated by Isolate.kill"));
            const UnwindError& error =
                UnwindError::Handle(UnwindError::New(msg));
            error.set_is_user_initiated(true);
            return error.ptr();
          } else if (msg_type == Isolate::kInternalKillMsg) {
            const String& msg =
                String::Handle(String::New("isolate terminated by vm"));
            return UnwindError::New(msg);
          } else {
            UNREACHABLE();
          }
        } else {
          return Error::null();
        }
      } else {
        ASSERT((priority == Isolate::kBeforeNextEventAction) ||
               (priority == Isolate::kAsEventAction));
        // Update the message so that it will be handled immediately when it
        // is picked up from the message queue the next time.
        message.SetAt(
            0, Smi::Handle(zone, Smi::New(Message::kDelayedIsolateLibOOBMsg)));
        message.SetAt(3,
                      Smi::Handle(zone, Smi::New(Isolate::kImmediateAction)));
        this->PostMessage(
            SerializeMessage(Message::kIllegalPort, message),
            priority == Isolate::kBeforeNextEventAction /* at_head */);
      }
      break;
    }
    case Isolate::kInterruptMsg: {
      // [ OOB, kInterruptMsg, pause capability ]
      if (message.Length() != 3) return Error::null();
      Object& obj = Object::Handle(zone, message.At(2));
      if (!I->VerifyPauseCapability(obj)) return Error::null();

#if !defined(PRODUCT)
      // If we are already paused, don't pause again.
      if (I->debugger()->PauseEvent() == nullptr) {
        return I->debugger()->PauseInterrupted();
      }
#endif
      break;
    }
    case Isolate::kDrainServiceExtensionsMsg: {
#ifndef PRODUCT
      Object& obj = Object::Handle(zone, message.At(2));
      if (!obj.IsSmi()) return Error::null();
      const intptr_t priority = Smi::Cast(obj).Value();
      if (priority == Isolate::kImmediateAction) {
        return I->InvokePendingServiceExtensionCalls();
      } else {
        ASSERT((priority == Isolate::kBeforeNextEventAction) ||
               (priority == Isolate::kAsEventAction));
        // Update the message so that it will be handled immediately when it
        // is picked up from the message queue the next time.
        message.SetAt(
            0, Smi::Handle(zone, Smi::New(Message::kDelayedIsolateLibOOBMsg)));
        message.SetAt(2,
                      Smi::Handle(zone, Smi::New(Isolate::kImmediateAction)));
        this->PostMessage(
            SerializeMessage(Message::kIllegalPort, message),
            priority == Isolate::kBeforeNextEventAction /* at_head */);
      }
#else
      UNREACHABLE();
#endif  // !PRODUCT
      break;
    }

    case Isolate::kAddExitMsg:
    case Isolate::kDelExitMsg:
    case Isolate::kAddErrorMsg:
    case Isolate::kDelErrorMsg: {
      // [ OOB, msg, listener port ]
      if (message.Length() < 3) return Error::null();
      const Object& obj = Object::Handle(zone, message.At(2));
      if (!obj.IsSendPort()) return Error::null();
      const SendPort& listener = SendPort::Cast(obj);
      switch (msg_type) {
        case Isolate::kAddExitMsg: {
          if (message.Length() != 4) return Error::null();
          // [ OOB, msg, listener port, response object ]
          const Object& response = Object::Handle(zone, message.At(3));
          if (!response.IsInstance() && !response.IsNull()) {
            return Error::null();
          }
          I->AddExitListener(listener, response.IsNull()
                                           ? Instance::null_instance()
                                           : Instance::Cast(response));
          break;
        }
        case Isolate::kDelExitMsg:
          if (message.Length() != 3) return Error::null();
          I->RemoveExitListener(listener);
          break;
        case Isolate::kAddErrorMsg:
          if (message.Length() != 3) return Error::null();
          I->AddErrorListener(listener);
          break;
        case Isolate::kDelErrorMsg:
          if (message.Length() != 3) return Error::null();
          I->RemoveErrorListener(listener);
          break;
        default:
          UNREACHABLE();
      }
      break;
    }
    case Isolate::kErrorFatalMsg: {
      // [ OOB, kErrorFatalMsg, terminate capability, val ]
      if (message.Length() != 4) return Error::null();
      // Check that the terminate capability has been passed correctly.
      Object& obj = Object::Handle(zone, message.At(2));
      if (!I->VerifyTerminateCapability(obj)) return Error::null();
      // Get the value to be set.
      obj = message.At(3);
      if (!obj.IsBool()) return Error::null();
      I->SetErrorsFatal(Bool::Cast(obj).value());
      break;
    }
    case Isolate::kCheckForReload: {
      // [ OOB, kCheckForReload, ignored ]
#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
      {
        ReloadParticipationScope allow_reload(T);
        T->CheckForSafepoint();
      }
#else
      UNREACHABLE();
#endif
      break;
    }
#if defined(DEBUG)
    // Malformed OOB messages are silently ignored in release builds.
    default:
      FATAL("Unknown OOB message type: %" Pd "\n", msg_type);
      break;
#endif  // defined(DEBUG)
  }
  return Error::null();
}

void IsolateMessageHandler::MessageNotify(Message::Priority priority) {
  if (priority >= Message::kOOBPriority) {
    // Handle out of band messages even if the mutator thread is busy.
    I->ScheduleInterrupts(Thread::kMessageInterrupt);
  }
  Dart_MessageNotifyCallback callback = I->message_notify_callback();
  if (callback != nullptr) {
    // Allow the embedder to handle message notification.
    (*callback)(Api::CastIsolate(I));
  }
}

bool Isolate::HasPendingMessages() {
  return message_handler_->HasMessages() || message_handler_->HasOOBMessages();
}

MessageHandler::MessageStatus IsolateMessageHandler::HandleMessage(
    std::unique_ptr<Message> message) {
  ASSERT(IsCurrentIsolate());
  Thread* thread = Thread::Current();
  StackZone stack_zone(thread);
  Zone* zone = stack_zone.GetZone();
  HandleScope handle_scope(thread);
#if defined(SUPPORT_TIMELINE)
  TimelineBeginEndScope tbes(
      thread, Timeline::GetIsolateStream(),
      message->IsOOB() ? "HandleOOBMessage" : "HandleMessage");
  tbes.SetNumArguments(1);
  tbes.CopyArgument(0, "isolateName", I->name());
#endif

  // Parse the message.
  Object& msg_obj = Object::Handle(zone, ReadMessage(thread, message.get()));
  if (msg_obj.IsError()) {
    // An error occurred while reading the message.
    return ProcessUnhandledException(Error::Cast(msg_obj));
  }
  if (!msg_obj.IsNull() && !msg_obj.IsInstance()) {
    // TODO(turnidge): We need to decide what an isolate does with
    // malformed messages.  If they (eventually) come from a remote
    // machine, then it might make sense to drop the message entirely.
    // In the case that the message originated locally, which is
    // always true for now, then this should never occur.
    UNREACHABLE();
  }
  Instance& msg = Instance::Handle(zone);
  msg ^= msg_obj.ptr();  // Can't use Instance::Cast because may be null.

  MessageStatus status = kOK;
  if (message->IsOOB()) {
    // OOB messages are expected to be fixed length arrays where the first
    // element is a Smi describing the OOB destination. Messages that do not
    // confirm to this layout are silently ignored.
    if (msg.IsArray()) {
      const Array& oob_msg = Array::Cast(msg);
      if (oob_msg.Length() > 0) {
        const Object& oob_tag = Object::Handle(zone, oob_msg.At(0));
        if (oob_tag.IsSmi()) {
          switch (Smi::Cast(oob_tag).Value()) {
            case Message::kServiceOOBMsg: {
#ifndef PRODUCT
              const Error& error =
                  Error::Handle(Service::HandleIsolateMessage(I, oob_msg));
              if (!error.IsNull()) {
                status = ProcessUnhandledException(error);
              }
#else
              UNREACHABLE();
#endif
              break;
            }
            case Message::kIsolateLibOOBMsg: {
              const Error& error = Error::Handle(HandleLibMessage(oob_msg));
              if (!error.IsNull()) {
                status = ProcessUnhandledException(error);
              }
              break;
            }
#if defined(DEBUG)
            // Malformed OOB messages are silently ignored in release builds.
            default: {
              UNREACHABLE();
              break;
            }
#endif  // defined(DEBUG)
          }
        }
      }
    }
  } else if (message->IsFinalizerInvocationRequest()) {
    const Object& msg_handler = Object::Handle(
        zone,
        DartLibraryCalls::HandleFinalizerMessage(FinalizerBase::Cast(msg)));
    if (msg_handler.IsError()) {
      status = ProcessUnhandledException(Error::Cast(msg_handler));
    } else {
      // The handler closure which was used to successfully handle the message.
    }
  } else if (message->dest_port() == Message::kIllegalPort) {
    // Check whether this is a delayed OOB message which needed handling as
    // part of the regular message dispatch. All other messages are dropped on
    // the floor.
    if (msg.IsArray()) {
      const Array& msg_arr = Array::Cast(msg);
      if (msg_arr.Length() > 0) {
        const Object& oob_tag = Object::Handle(zone, msg_arr.At(0));
        if (oob_tag.IsSmi() &&
            (Smi::Cast(oob_tag).Value() == Message::kDelayedIsolateLibOOBMsg)) {
          const Error& error = Error::Handle(HandleLibMessage(msg_arr));
          if (!error.IsNull()) {
            status = ProcessUnhandledException(error);
          }
        }
      }
    }
  } else {
    const Object& msg_handler = Object::Handle(
        zone, DartLibraryCalls::HandleMessage(message->dest_port(), msg));
    if (msg_handler.IsError()) {
      status = ProcessUnhandledException(Error::Cast(msg_handler));
    } else if (msg_handler.IsNull()) {
      // If the port has been closed then the message will be dropped at this
      // point. Make sure to post to the delivery failure port in that case.
    } else {
      // The handler closure which was used to successfully handle the message.
    }
  }
  return status;
}

#ifndef PRODUCT
void IsolateMessageHandler::NotifyPauseOnStart() {
  if (Isolate::IsSystemIsolate(I)) {
    return;
  }
  if (Service::debug_stream.enabled() || FLAG_warn_on_pause_with_no_debugger) {
    StartIsolateScope start_isolate(I);
    StackZone zone(T);
    HandleScope handle_scope(T);
    ServiceEvent pause_event(I, ServiceEvent::kPauseStart);
    Service::HandleEvent(&pause_event);
  } else if (FLAG_trace_service) {
    OS::PrintErr("vm-service: Dropping event of type PauseStart (%s)\n",
                 I->name());
  }
}

void IsolateMessageHandler::NotifyPauseOnExit() {
  if (Isolate::IsSystemIsolate(I)) {
    return;
  }
  if (Service::debug_stream.enabled() || FLAG_warn_on_pause_with_no_debugger) {
    StartIsolateScope start_isolate(I);
    StackZone zone(T);
    HandleScope handle_scope(T);
    ServiceEvent pause_event(I, ServiceEvent::kPauseExit);
    Service::HandleEvent(&pause_event);
  } else if (FLAG_trace_service) {
    OS::PrintErr("vm-service: Dropping event of type PauseExit (%s)\n",
                 I->name());
  }
}
#endif  // !PRODUCT

#if defined(DEBUG)
void IsolateMessageHandler::CheckAccess() const {
  ASSERT(IsCurrentIsolate());
}
#endif

bool IsolateMessageHandler::IsCurrentIsolate() const {
  return (I == Isolate::Current());
}

static MessageHandler::MessageStatus StoreError(Thread* thread,
                                                const Error& error) {
  thread->set_sticky_error(error);
  if (error.IsUnwindError()) {
    const UnwindError& unwind = UnwindError::Cast(error);
    if (!unwind.is_user_initiated()) {
      return MessageHandler::kShutdown;
    }
  }
  return MessageHandler::kError;
}

MessageHandler::MessageStatus IsolateMessageHandler::ProcessUnhandledException(
    const Error& result) {
  if (FLAG_trace_isolates) {
    OS::PrintErr(
        "[!] Unhandled exception in %s:\n"
        "         exception: %s\n",
        T->isolate()->name(), result.ToErrorCString());
  }

  NoReloadScope no_reload(T);
  // Generate the error and stacktrace strings for the error message.
  const char* exception_cstr = nullptr;
  const char* stacktrace_cstr = nullptr;
  if (result.IsUnhandledException()) {
    Zone* zone = T->zone();
    const UnhandledException& uhe = UnhandledException::Cast(result);
    const Instance& exception = Instance::Handle(zone, uhe.exception());
    if (exception.ptr() == IG->object_store()->out_of_memory()) {
      exception_cstr = "Out of Memory";  // Cf. OutOfMemoryError.toString().
    } else if (exception.ptr() == IG->object_store()->stack_overflow()) {
      exception_cstr = "Stack Overflow";  // Cf. StackOverflowError.toString().
    } else {
      const Object& exception_str =
          Object::Handle(zone, DartLibraryCalls::ToString(exception));
      if (!exception_str.IsString()) {
        exception_cstr = exception.ToCString();
      } else {
        exception_cstr = exception_str.ToCString();
      }
    }

    const Instance& stacktrace = Instance::Handle(zone, uhe.stacktrace());
    stacktrace_cstr = stacktrace.ToCString();
  } else {
    exception_cstr = result.ToErrorCString();
  }
  if (result.IsUnwindError()) {
    // When unwinding we don't notify error listeners and we ignore
    // whether errors are fatal for the current isolate.
    return StoreError(T, result);
  } else {
    bool has_listener =
        I->NotifyErrorListeners(exception_cstr, stacktrace_cstr);
    if (I->ErrorsFatal()) {
      if (has_listener) {
        T->ClearStickyError();
      } else {
        T->set_sticky_error(result);
      }
#if !defined(PRODUCT)
      // Notify the debugger about specific unhandled exceptions which are
      // withheld when being thrown. Do this after setting the sticky error
      // so the isolate has an error set when paused with the unhandled
      // exception.
      if (result.IsUnhandledException()) {
        const UnhandledException& error = UnhandledException::Cast(result);
        InstancePtr exception = error.exception();
        if ((exception == IG->object_store()->out_of_memory()) ||
            (exception == IG->object_store()->stack_overflow())) {
          // We didn't notify the debugger when the stack was full. Do it now.
          I->debugger()->PauseException(Instance::Handle(exception));
        }
      }
#endif  // !defined(PRODUCT)
      return kError;
    }
  }
  return kOK;
}

void IsolateGroup::FlagsInitialize(Dart_IsolateFlags* api_flags) {
  api_flags->version = DART_FLAGS_CURRENT_VERSION;
#define INIT_FROM_FLAG(when, name, bitname, isolate_flag, flag)                \
  api_flags->isolate_flag = flag;
  BOOL_ISOLATE_GROUP_FLAG_LIST(INIT_FROM_FLAG)
#undef INIT_FROM_FLAG
  api_flags->is_service_isolate = false;
  api_flags->is_kernel_isolate = false;
  api_flags->null_safety = true;
}

void IsolateGroup::FlagsCopyTo(Dart_IsolateFlags* api_flags) {
  api_flags->version = DART_FLAGS_CURRENT_VERSION;
#define INIT_FROM_FIELD(when, name, bitname, isolate_flag, flag)               \
  api_flags->isolate_flag = name();
  BOOL_ISOLATE_GROUP_FLAG_LIST(INIT_FROM_FIELD)
#undef INIT_FROM_FIELD
  api_flags->is_service_isolate = false;
  api_flags->is_kernel_isolate = false;
  api_flags->null_safety = true;
}

void IsolateGroup::FlagsCopyFrom(const Dart_IsolateFlags& api_flags) {
#if defined(DART_PRECOMPILER)
#define FLAG_FOR_PRECOMPILER(action) action
#else
#define FLAG_FOR_PRECOMPILER(action)
#endif

#if !defined(PRODUCT)
#define FLAG_FOR_NONPRODUCT(action) action
#else
#define FLAG_FOR_NONPRODUCT(action)
#endif

#define FLAG_FOR_PRODUCT(action) action

#define SET_FROM_FLAG(when, name, bitname, isolate_flag, flag)                 \
  FLAG_FOR_##when(isolate_group_flags_ = bitname##Bit::update(                 \
                      api_flags.isolate_flag, isolate_group_flags_));

  BOOL_ISOLATE_GROUP_FLAG_LIST(SET_FROM_FLAG)
#undef FLAG_FOR_NONPRODUCT
#undef FLAG_FOR_PRECOMPILER
#undef FLAG_FOR_PRODUCT
#undef SET_FROM_FLAG
}

void Isolate::FlagsInitialize(Dart_IsolateFlags* api_flags) {
  IsolateGroup::FlagsInitialize(api_flags);

  api_flags->version = DART_FLAGS_CURRENT_VERSION;
#define INIT_FROM_FLAG(when, name, bitname, isolate_flag, flag)                \
  api_flags->isolate_flag = flag;
  BOOL_ISOLATE_FLAG_LIST(INIT_FROM_FLAG)
#undef INIT_FROM_FLAG
  api_flags->is_service_isolate = false;
  api_flags->is_kernel_isolate = false;
  api_flags->null_safety = true;
}

void Isolate::FlagsCopyTo(Dart_IsolateFlags* api_flags) const {
  group()->FlagsCopyTo(api_flags);

  api_flags->version = DART_FLAGS_CURRENT_VERSION;
#define INIT_FROM_FIELD(when, name, bitname, isolate_flag, flag)               \
  api_flags->isolate_flag = name();
  BOOL_ISOLATE_FLAG_LIST(INIT_FROM_FIELD)
#undef INIT_FROM_FIELD
  api_flags->is_service_isolate = false;
  api_flags->is_kernel_isolate = false;
  api_flags->null_safety = true;
}

void Isolate::FlagsCopyFrom(const Dart_IsolateFlags& api_flags) {
#if defined(DART_PRECOMPILER)
#define FLAG_FOR_PRECOMPILER(action) action
#else
#define FLAG_FOR_PRECOMPILER(action)
#endif

#if !defined(PRODUCT)
#define FLAG_FOR_NONPRODUCT(action) action
#else
#define FLAG_FOR_NONPRODUCT(action)
#endif

#define FLAG_FOR_PRODUCT(action) action

#define SET_FROM_FLAG(when, name, bitname, isolate_flag, flag)                 \
  FLAG_FOR_##when(isolate_flags_ = bitname##Bit::update(                       \
                      api_flags.isolate_flag, isolate_flags_));

  BOOL_ISOLATE_FLAG_LIST(SET_FROM_FLAG)
#undef FLAG_FOR_NONPRODUCT
#undef FLAG_FOR_PRECOMPILER
#undef FLAG_FOR_PRODUCT
#undef SET_FROM_FLAG
}

#if defined(DEBUG)
// static
void BaseIsolate::AssertCurrent(BaseIsolate* isolate) {
  ASSERT(isolate == Isolate::Current());
}
#endif  // defined(DEBUG)

#if defined(DEBUG)
#define REUSABLE_HANDLE_SCOPE_INIT(object)                                     \
  reusable_##object##_handle_scope_active_(false),
#else
#define REUSABLE_HANDLE_SCOPE_INIT(object)
#endif  // defined(DEBUG)

#define REUSABLE_HANDLE_INITIALIZERS(object) object##_handle_(nullptr),

class LibraryPrefixMapTraits {
 public:
  static bool ReportStats() { return false; }
  static const char* Name() { return "LibraryPrefixMapTraits"; }

  static bool IsMatch(const Object& a, const Object& b) {
    if (!a.IsLibraryPrefix() || !b.IsLibraryPrefix()) {
      return false;
    }
    return a.ptr() == b.ptr();
  }

  static uword Hash(const Object& obj) {
    auto& prefix = LibraryPrefix::Cast(obj);
    return String::Hash(prefix.name());
  }
};

// TODO(srdjan): Some Isolate monitors can be shared. Replace their usage with
// that shared monitor.
Isolate::Isolate(IsolateGroup* isolate_group,
                 const Dart_IsolateFlags& api_flags)
    : BaseIsolate(),
      current_tag_(UserTag::null()),
      default_tag_(UserTag::null()),
      field_table_(new FieldTable(/*isolate=*/this)),
      finalizers_(GrowableObjectArray::null()),
      isolate_group_(isolate_group),
      isolate_object_store_(new IsolateObjectStore()),
      isolate_flags_(0),
#if !defined(PRODUCT)
      last_resume_timestamp_(OS::GetCurrentTimeMillis()),
      vm_tag_counters_(),
      pending_service_extension_calls_(GrowableObjectArray::null()),
      registered_service_extension_handlers_(GrowableObjectArray::null()),
      service_id_zones_(nullptr),
#define ISOLATE_METRIC_CONSTRUCTORS(type, variable, name, unit)                \
  metric_##variable##_(),
      ISOLATE_METRIC_LIST(ISOLATE_METRIC_CONSTRUCTORS)
#undef ISOLATE_METRIC_CONSTRUCTORS
#endif  // !defined(PRODUCT)
          start_time_micros_(OS::GetCurrentMonotonicMicros()),
      message_notify_callback_(nullptr),
      on_shutdown_callback_(Isolate::ShutdownCallback()),
      on_cleanup_callback_(Isolate::CleanupCallback()),
      random_(),
      mutex_(),
      tag_table_(GrowableObjectArray::null()),
      sticky_error_(Error::null()),
      spawn_count_monitor_(),
      handler_info_cache_(),
      catch_entry_moves_cache_(),
      wake_pause_event_handler_count_(0),
      loaded_prefixes_set_storage_(nullptr) {
  FlagsCopyFrom(api_flags);
  SetErrorsFatal(true);
  // TODO(asiva): A Thread is not available here, need to figure out
  // how the vm_tag (kEmbedderTagId) can be set, these tags need to
  // move to the OSThread structure.
  set_user_tag(UserTags::kDefaultUserTag);
}

#undef REUSABLE_HANDLE_SCOPE_INIT
#undef REUSABLE_HANDLE_INITIALIZERS

Isolate::~Isolate() {
#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
  // TODO(32796): Re-enable assertion.
  // RELEASE_ASSERT(program_reload_context_ == nullptr);
#endif  // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)

#if !defined(PRODUCT)
  delete debugger_;
  debugger_ = nullptr;
  if (service_id_zones_ != nullptr) {
    for (intptr_t i = 0; i < service_id_zones_->length(); ++i) {
      delete service_id_zones_->At(i);
    }
    delete service_id_zones_;
    service_id_zones_ = nullptr;
  }
  delete pause_loop_monitor_;
  pause_loop_monitor_ = nullptr;
#endif  // !defined(PRODUCT)

  free(name_);
  delete field_table_;
#if defined(USING_SIMULATOR)
  delete simulator_;
#endif
  delete message_handler_;
  message_handler_ =
      nullptr;  // Fail fast if we send messages to a dead isolate.
  ASSERT(deopt_context_ ==
         nullptr);  // No deopt in progress when isolate deleted.
  ASSERT(spawn_count_ == 0);

  // The [Thread] object should've been released on the last
  // `Thread::ExitIsolate()` call.
  ASSERT(scheduled_mutator_thread_ == nullptr);
  ASSERT(mutator_thread_ == nullptr);
}

void Isolate::InitVM() {
  create_group_callback_ = nullptr;
  initialize_callback_ = nullptr;
  shutdown_callback_ = nullptr;
  cleanup_callback_ = nullptr;
  cleanup_group_callback_ = nullptr;
  register_kernel_blob_callback_ = nullptr;
  unregister_kernel_blob_callback_ = nullptr;
  if (isolate_creation_monitor_ == nullptr) {
    isolate_creation_monitor_ = new Monitor();
  }
  ASSERT(isolate_creation_monitor_ != nullptr);
  EnableIsolateCreation();
}

Isolate* Isolate::InitIsolate(const char* name_prefix,
                              IsolateGroup* isolate_group,
                              const Dart_IsolateFlags& api_flags,
                              bool is_vm_isolate) {
  Isolate* result = new Isolate(isolate_group, api_flags);
  result->set_is_vm_isolate(is_vm_isolate);
  result->BuildName(name_prefix);
  if (!is_vm_isolate) {
    // vm isolate object store is initialized later, after null instance
    // is created (in Dart::Init).
    // Non-vm isolates need to have isolate object store initialized is that
    // exit_listeners have to be null-initialized as they will be used if
    // we fail to create isolate below, have to do low level shutdown.
    ASSERT(result->group()->object_store() != nullptr);
    result->isolate_object_store()->Init();
  }

  ASSERT(result != nullptr);

#if !defined(PRODUCT)
// Initialize metrics.
#define ISOLATE_METRIC_INIT(type, variable, name, unit)                        \
  result->metric_##variable##_.InitInstance(result, name, nullptr,             \
                                            Metric::unit);
  ISOLATE_METRIC_LIST(ISOLATE_METRIC_INIT);
#undef ISOLATE_METRIC_INIT
#endif  // !defined(PRODUCT)

  // First we ensure we enter the isolate. This will ensure we're participating
  // in any safepointing requests from this point on. Other threads requesting a
  // safepoint operation will therefore wait until we've stopped.
  //
  // Though the [result] isolate is still in a state where no memory has been
  // allocated, which means it's safe to GC the isolate group until here.
  Thread::EnterIsolate(result);

  // Setup the isolate message handler.
  result->message_handler_ = new IsolateMessageHandler(result);

  result->set_main_port(PortMap::CreatePort(result->message_handler()));
#if defined(DEBUG)
  // Verify that we are never reusing a live origin id.
  VerifyOriginId id_verifier(result->main_port());
  Isolate::VisitIsolates(&id_verifier);
#endif
  result->set_origin_id(result->main_port());

  // Keep capability IDs less than 2^53 so web clients of the service
  // protocol can process it properly.
  //
  // See https://github.com/dart-lang/sdk/issues/53081.
  result->set_pause_capability(result->random()->NextJSInt());
  result->set_terminate_capability(result->random()->NextJSInt());

#if !defined(PRODUCT)
  result->debugger_ = new Debugger(result);
#endif  // !defined(PRODUCT)

  // Now we register the isolate in the group. From this point on any GC would
  // traverse the isolate roots (before this point, the roots are only pointing
  // to vm-isolate objects, e.g. null)
  isolate_group->RegisterIsolate(result);

  if (api_flags.is_service_isolate) {
    ASSERT(!ServiceIsolate::Exists());
    ServiceIsolate::SetServiceIsolate(result);
#if !defined(DART_PRECOMPILED_RUNTIME)
  } else if (api_flags.is_kernel_isolate) {
    ASSERT(!KernelIsolate::Exists());
    KernelIsolate::SetKernelIsolate(result);
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
  }

  if (FLAG_trace_isolates) {
    if (name_prefix == nullptr || strcmp(name_prefix, "vm-isolate") != 0) {
      OS::PrintErr(
          "[+] Starting isolate:\n"
          "\tisolate:    %s\n",
          result->name());
    }
  }

  // Add to isolate list. Shutdown and delete the isolate on failure.
  if (!TryMarkIsolateReady(result)) {
    result->LowLevelShutdown();
    Isolate::LowLevelCleanup(result);
    return nullptr;
  }

  return result;
}

Thread* Isolate::mutator_thread() const {
  ASSERT(thread_registry() != nullptr);
  return mutator_thread_;
}

ObjectPtr IsolateGroup::CallTagHandler(Dart_LibraryTag tag,
                                       const Object& arg1,
                                       const Object& arg2) {
  Thread* thread = Thread::Current();
  Api::Scope api_scope(thread);
  Dart_Handle api_arg1 = Api::NewHandle(thread, arg1.ptr());
  Dart_Handle api_arg2 = Api::NewHandle(thread, arg2.ptr());
  Dart_Handle api_result;
  {
    TransitionVMToNative transition(thread);
    ASSERT(HasTagHandler());
    api_result = library_tag_handler()(tag, api_arg1, api_arg2);
  }
  return Api::UnwrapHandle(api_result);
}

ObjectPtr Isolate::CallDeferredLoadHandler(intptr_t id) {
  Thread* thread = Thread::Current();
  Api::Scope api_scope(thread);
  Dart_Handle api_result;
  {
    TransitionVMToNative transition(thread);
    RELEASE_ASSERT(HasDeferredLoadHandler());
    api_result = group()->deferred_load_handler()(id);
  }
  return Api::UnwrapHandle(api_result);
}

void IsolateGroup::SetupImagePage(const uint8_t* image_buffer,
                                  bool is_executable) {
  Image image(image_buffer);
  heap()->SetupImagePage(image.object_start(), image.object_size(),
                         is_executable);
}

void IsolateGroup::ScheduleInterrupts(uword interrupt_bits) {
  SafepointReadRwLocker ml(Thread::Current(), isolates_lock_.get());
  for (Isolate* isolate : isolates_) {
    isolate->ScheduleInterrupts(interrupt_bits);
  }
}

void Isolate::ScheduleInterrupts(uword interrupt_bits) {
  // We take the threads lock here to ensure that the mutator thread does not
  // exit the isolate while we are trying to schedule interrupts on it.
  MonitorLocker ml(group()->thread_registry()->threads_lock());
  Thread* mthread = mutator_thread();
  if (mthread != nullptr) {
    mthread->ScheduleInterrupts(interrupt_bits);
  }
}

void Isolate::set_name(const char* name) {
  free(name_);
  name_ = Utils::StrDup(name);
}

int64_t IsolateGroup::UptimeMicros() const {
  return OS::GetCurrentMonotonicMicros() - start_time_micros_;
}

int64_t Isolate::UptimeMicros() const {
  return OS::GetCurrentMonotonicMicros() - start_time_micros_;
}

Dart_Port Isolate::origin_id() {
  MutexLocker ml(&origin_id_mutex_);
  return origin_id_;
}

void Isolate::set_origin_id(Dart_Port id) {
  MutexLocker ml(&origin_id_mutex_);
  ASSERT((id == main_port_ && origin_id_ == 0) || (origin_id_ == main_port_));
  origin_id_ = id;
}

void Isolate::set_finalizers(const GrowableObjectArray& value) {
  finalizers_ = value.ptr();
}

bool Isolate::IsPaused() const {
#if defined(PRODUCT)
  return false;
#else
  return (debugger_ != nullptr) && (debugger_->PauseEvent() != nullptr);
#endif  // !defined(PRODUCT)
}

ErrorPtr Isolate::PausePostRequest() {
#if !defined(PRODUCT)
  if (debugger_ == nullptr) {
    return Error::null();
  }
  ASSERT(!IsPaused());
  const Error& error = Error::Handle(debugger_->PausePostRequest());
  if (!error.IsNull()) {
    if (Thread::Current()->top_exit_frame_info() == 0) {
      return error.ptr();
    } else {
      Exceptions::PropagateError(error);
      UNREACHABLE();
    }
  }
#endif
  return Error::null();
}

void Isolate::BuildName(const char* name_prefix) {
  ASSERT(name_ == nullptr);
  if (name_prefix == nullptr) {
    name_ = OS::SCreate(nullptr, "isolate-%" Pd64 "", main_port());
  } else {
    name_ = Utils::StrDup(name_prefix);
  }
}

#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
bool IsolateGroup::CanReload() {
  // We only call this method on the mutator thread. Normally the caller is
  // inside of the "reloadSources" service OOB message handler. Though
  // we also use it in the slow path of StackOverflowCheck in the artificial
  // --hot-reload-test-mode like flags.
  //
  // During reload itself we don't process OOB messages and don't execute Dart
  // code, so the caller should implicitly have a guarantee we're not reloading
  // already.
  RELEASE_ASSERT(!Thread::Current()->OwnsReloadSafepoint());

  // We only allow reload to take place from the point on where the first
  // isolate within an isolate group has setup it's root library. From that
  // point on it's safe to perform hot-reload.
  auto thread = Thread::Current();
  if (object_store()->root_library() == Library::null()) {
    return false;
  }

  // We only care about the current thread's [NoReloadScope]. If we're inside
  // one we cannot reload right now. Though if another isolate's mutator
  // thread is inside such a scope, the multi-isolate reload will simply wait
  // until it's out of that scope again.
  if (thread->no_reload_scope_depth_ != 0) {
    return false;
  }

  return !IsolateGroup::IsSystemIsolateGroup(this) &&
         OSThread::Current()->HasStackHeadroom(64 * KB);
}

bool IsolateGroup::ReloadSources(JSONStream* js,
                                 bool force_reload,
                                 const char* root_script_url,
                                 const char* packages_url,
                                 bool dont_delete_reload_context) {
  ASSERT(!IsReloading());

  // Ensure all isolates inside the isolate group are paused at a place where we
  // can safely do a reload.
  RELOAD_OPERATION_SCOPE(Thread::Current());

  auto class_table = IsolateGroup::Current()->class_table();
  std::shared_ptr<IsolateGroupReloadContext> group_reload_context(
      new IsolateGroupReloadContext(this, class_table, js));
  group_reload_context_ = group_reload_context;

  SetHasAttemptedReload(true);
  program_reload_context_ =
      new ProgramReloadContext(group_reload_context_, this);
  const bool success =
      group_reload_context_->Reload(force_reload, root_script_url, packages_url,
                                    /*kernel_buffer=*/nullptr,
                                    /*kernel_buffer_size=*/0);
  if (!dont_delete_reload_context) {
    DeleteReloadContext();
  }
  return success;
}

bool IsolateGroup::ReloadKernel(JSONStream* js,
                                bool force_reload,
                                const uint8_t* kernel_buffer,
                                intptr_t kernel_buffer_size,
                                bool dont_delete_reload_context) {
  ASSERT(!IsReloading());

  // Ensure all isolates inside the isolate group are paused at a place where we
  // can safely do a reload.
  RELOAD_OPERATION_SCOPE(Thread::Current());

  auto class_table = IsolateGroup::Current()->class_table();
  std::shared_ptr<IsolateGroupReloadContext> group_reload_context(
      new IsolateGroupReloadContext(this, class_table, js));
  group_reload_context_ = group_reload_context;

  SetHasAttemptedReload(true);
  program_reload_context_ =
      new ProgramReloadContext(group_reload_context_, this);
  const bool success = group_reload_context_->Reload(
      force_reload,
      /*root_script_url=*/nullptr,
      /*packages_url=*/nullptr, kernel_buffer, kernel_buffer_size);
  if (!dont_delete_reload_context) {
    DeleteReloadContext();
  }
  return success;
}

void IsolateGroup::DeleteReloadContext() {
  GcSafepointOperationScope safepoint_scope(Thread::Current());
  group_reload_context_.reset();

  delete program_reload_context_;
  program_reload_context_ = nullptr;
}
#endif  // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)

const char* Isolate::MakeRunnable() {
  MutexLocker ml(&mutex_);
  // Check if we are in a valid state to make the isolate runnable.
  if (is_runnable() == true) {
    return "Isolate is already runnable";
  }
  if (group()->object_store()->root_library() == Library::null()) {
    return "The embedder has to ensure there is a root library (e.g. by "
           "calling Dart_LoadScriptFromKernel ).";
  }
  MakeRunnableLocked();
  return nullptr;
}

void Isolate::MakeRunnableLocked() {
  ASSERT(mutex_.IsOwnedByCurrentThread());
  ASSERT(!is_runnable());
  ASSERT(group()->object_store()->root_library() != Library::null());

  // Set the isolate as runnable and if we are being spawned schedule
  // isolate on thread pool for execution.
  set_is_runnable(true);
#ifndef PRODUCT
  if (!Isolate::IsSystemIsolate(this)) {
    if (FLAG_pause_isolates_on_unhandled_exceptions) {
      debugger()->SetExceptionPauseInfo(kPauseOnUnhandledExceptions);
    }
  }
#endif  // !PRODUCT
#if defined(SUPPORT_TIMELINE)
  TimelineStream* stream = Timeline::GetIsolateStream();
  ASSERT(stream != nullptr);
  TimelineEvent* event = stream->StartEvent();
  if (event != nullptr) {
    event->Instant("Runnable");
    event->Complete();
  }
#endif
#ifndef PRODUCT
  if (!Isolate::IsSystemIsolate(this) && Service::isolate_stream.enabled()) {
    ServiceEvent runnableEvent(this, ServiceEvent::kIsolateRunnable);
    Service::HandleEvent(&runnableEvent, /* enter_safepoint */ false);
  }
  GetRunnableLatencyMetric()->set_value(UptimeMicros());
#endif  // !PRODUCT
}

bool Isolate::VerifyPauseCapability(const Object& capability) const {
  return !capability.IsNull() && capability.IsCapability() &&
         (pause_capability() == Capability::Cast(capability).Id());
}

bool Isolate::VerifyTerminateCapability(const Object& capability) const {
  return !capability.IsNull() && capability.IsCapability() &&
         (terminate_capability() == Capability::Cast(capability).Id());
}

bool Isolate::AddResumeCapability(const Capability& capability) {
  // Ensure a limit for the number of resume capabilities remembered.
  const intptr_t kMaxResumeCapabilities =
      compiler::target::kSmiMax / (6 * kWordSize);

  const GrowableObjectArray& caps = GrowableObjectArray::Handle(
      current_zone(), isolate_object_store()->resume_capabilities());
  Capability& current = Capability::Handle(current_zone());
  intptr_t insertion_index = -1;
  for (intptr_t i = 0; i < caps.Length(); i++) {
    current ^= caps.At(i);
    if (current.IsNull()) {
      if (insertion_index < 0) {
        insertion_index = i;
      }
    } else if (current.Id() == capability.Id()) {
      return false;
    }
  }
  if (insertion_index < 0) {
    if (caps.Length() >= kMaxResumeCapabilities) {
      // Cannot grow the array of resume capabilities beyond its max. Additional
      // pause requests are ignored. In practice will never happen as we will
      // run out of memory beforehand.
      return false;
    }
    caps.Add(capability);
  } else {
    caps.SetAt(insertion_index, capability);
  }
  return true;
}

bool Isolate::RemoveResumeCapability(const Capability& capability) {
  const GrowableObjectArray& caps = GrowableObjectArray::Handle(
      current_zone(), isolate_object_store()->resume_capabilities());
  Capability& current = Capability::Handle(current_zone());
  for (intptr_t i = 0; i < caps.Length(); i++) {
    current ^= caps.At(i);
    if (!current.IsNull() && (current.Id() == capability.Id())) {
      // Remove the matching capability from the list.
      current = Capability::null();
      caps.SetAt(i, current);
      return true;
    }
  }
  return false;
}

// TODO(iposva): Remove duplicated code and start using some hash based
// structure instead of these linear lookups.
void Isolate::AddExitListener(const SendPort& listener,
                              const Instance& response) {
  // Ensure a limit for the number of listeners remembered.
  const intptr_t kMaxListeners = compiler::target::kSmiMax / (12 * kWordSize);

  const GrowableObjectArray& listeners = GrowableObjectArray::Handle(
      current_zone(), isolate_object_store()->exit_listeners());
  SendPort& current = SendPort::Handle(current_zone());
  intptr_t insertion_index = -1;
  for (intptr_t i = 0; i < listeners.Length(); i += 2) {
    current ^= listeners.At(i);
    if (current.IsNull()) {
      if (insertion_index < 0) {
        insertion_index = i;
      }
    } else if (current.Id() == listener.Id()) {
      listeners.SetAt(i + 1, response);
      return;
    }
  }
  if (insertion_index < 0) {
    if (listeners.Length() >= kMaxListeners) {
      // Cannot grow the array of listeners beyond its max. Additional
      // listeners are ignored. In practice will never happen as we will
      // run out of memory beforehand.
      return;
    }
    listeners.Add(listener);
    listeners.Add(response);
  } else {
    listeners.SetAt(insertion_index, listener);
    listeners.SetAt(insertion_index + 1, response);
  }
}

void Isolate::RemoveExitListener(const SendPort& listener) {
  const GrowableObjectArray& listeners = GrowableObjectArray::Handle(
      current_zone(), isolate_object_store()->exit_listeners());
  SendPort& current = SendPort::Handle(current_zone());
  for (intptr_t i = 0; i < listeners.Length(); i += 2) {
    current ^= listeners.At(i);
    if (!current.IsNull() && (current.Id() == listener.Id())) {
      // Remove the matching listener from the list.
      current = SendPort::null();
      listeners.SetAt(i, current);
      listeners.SetAt(i + 1, Object::null_instance());
      return;
    }
  }
}

void Isolate::NotifyExitListeners() {
  const GrowableObjectArray& listeners = GrowableObjectArray::Handle(
      current_zone(), isolate_object_store()->exit_listeners());
  if (listeners.IsNull()) return;

  SendPort& listener = SendPort::Handle(current_zone());
  Instance& response = Instance::Handle(current_zone());
  for (intptr_t i = 0; i < listeners.Length(); i += 2) {
    listener ^= listeners.At(i);
    if (!listener.IsNull()) {
      Dart_Port port_id = listener.Id();
      response ^= listeners.At(i + 1);
      PortMap::PostMessage(SerializeMessage(port_id, response));
    }
  }
}

void Isolate::AddErrorListener(const SendPort& listener) {
  // Ensure a limit for the number of listeners remembered.
  const intptr_t kMaxListeners = compiler::target::kSmiMax / (6 * kWordSize);

  const GrowableObjectArray& listeners = GrowableObjectArray::Handle(
      current_zone(), isolate_object_store()->error_listeners());
  SendPort& current = SendPort::Handle(current_zone());
  intptr_t insertion_index = -1;
  for (intptr_t i = 0; i < listeners.Length(); i++) {
    current ^= listeners.At(i);
    if (current.IsNull()) {
      if (insertion_index < 0) {
        insertion_index = i;
      }
    } else if (current.Id() == listener.Id()) {
      return;
    }
  }
  if (insertion_index < 0) {
    if (listeners.Length() >= kMaxListeners) {
      // Cannot grow the array of listeners beyond its max. Additional
      // listeners are ignored. In practice will never happen as we will
      // run out of memory beforehand.
      return;
    }
    listeners.Add(listener);
  } else {
    listeners.SetAt(insertion_index, listener);
  }
}

void Isolate::RemoveErrorListener(const SendPort& listener) {
  const GrowableObjectArray& listeners = GrowableObjectArray::Handle(
      current_zone(), isolate_object_store()->error_listeners());
  SendPort& current = SendPort::Handle(current_zone());
  for (intptr_t i = 0; i < listeners.Length(); i++) {
    current ^= listeners.At(i);
    if (!current.IsNull() && (current.Id() == listener.Id())) {
      // Remove the matching listener from the list.
      current = SendPort::null();
      listeners.SetAt(i, current);
      return;
    }
  }
}

bool Isolate::NotifyErrorListeners(const char* message,
                                   const char* stacktrace) {
  const GrowableObjectArray& listeners = GrowableObjectArray::Handle(
      current_zone(), isolate_object_store()->error_listeners());
  if (listeners.IsNull()) return false;

  Dart_CObject arr;
  Dart_CObject* arr_values[2];
  arr.type = Dart_CObject_kArray;
  arr.value.as_array.length = 2;
  arr.value.as_array.values = arr_values;
  Dart_CObject msg;
  msg.type = Dart_CObject_kString;
  msg.value.as_string = const_cast<char*>(message);
  arr_values[0] = &msg;
  Dart_CObject stack;
  if (stacktrace == nullptr) {
    stack.type = Dart_CObject_kNull;
  } else {
    stack.type = Dart_CObject_kString;
    stack.value.as_string = const_cast<char*>(stacktrace);
  }
  arr_values[1] = &stack;

  SendPort& listener = SendPort::Handle(current_zone());
  bool was_somebody_notified = false;
  for (intptr_t i = 0; i < listeners.Length(); i++) {
    listener ^= listeners.At(i);
    if (!listener.IsNull()) {
      Dart_Port port_id = listener.Id();
      PortMap::PostMessage(SerializeMessage(current_zone(), port_id, &arr));
      was_somebody_notified = true;
    }
  }
  return was_somebody_notified;
}

static void ShutdownIsolate(uword parameter) {
  Dart_EnterIsolate(reinterpret_cast<Dart_Isolate>(parameter));
  Dart_ShutdownIsolate();
}

void Isolate::SetStickyError(ErrorPtr sticky_error) {
  ASSERT(
      ((sticky_error_ == Error::null()) || (sticky_error == Error::null())) &&
      (sticky_error != sticky_error_));
  sticky_error_ = sticky_error;
}

void Isolate::Run() {
  message_handler()->Run(group()->thread_pool(), nullptr, ShutdownIsolate,
                         reinterpret_cast<uword>(this));
}

MessageHandler* Isolate::message_handler() const {
  return message_handler_;
}

void Isolate::RunAndCleanupFinalizersOnShutdown() {
  if (finalizers_ == GrowableObjectArray::null()) return;

  // Ensure we have a zone and handle scope so that we can call VM functions,
  // but we no longer allocate new heap objects.
  Thread* thread = Thread::Current();
  StackZone stack_zone(thread);
  HandleScope handle_scope(thread);
  NoSafepointScope no_safepoint_scope;

  // Set live finalizers isolate to null, before deleting the message handler.
  const auto& finalizers =
      GrowableObjectArray::Handle(stack_zone.GetZone(), finalizers_);
  if (!finalizers.IsNull()) {
    const intptr_t num_finalizers = finalizers.Length();
    auto& weak_reference = WeakReference::Handle(stack_zone.GetZone());
    auto& finalizer = FinalizerBase::Handle(stack_zone.GetZone());
    auto& current_entry = FinalizerEntry::Handle(stack_zone.GetZone());
    auto& all_entries = Set::Handle(stack_zone.GetZone());
    for (int i = 0; i < num_finalizers; i++) {
      weak_reference ^= finalizers.At(i);
      finalizer ^= weak_reference.target();
      if (!finalizer.IsNull()) {
        if (finalizer.isolate() == this) {
          if (FLAG_trace_finalizers) {
            THR_Print("Isolate %p Setting finalizer %p isolate to null\n", this,
                      finalizer.ptr()->untag());
          }
          // Finalizer was not sent to another isolate with send and exit.
          finalizer.set_isolate(nullptr);
        } else {
          // TODO(http://dartbug.com/47777): Send and exit support.
          UNREACHABLE();
        }

        if (finalizer.IsNativeFinalizer()) {
          // Immediately call native callback.
          const auto& native_finalizer = NativeFinalizer::Cast(finalizer);
          all_entries = finalizer.all_entries();
          Set::Iterator iterator(all_entries);
          while (iterator.MoveNext()) {
            current_entry ^= iterator.CurrentKey();
            native_finalizer.RunCallback(current_entry, "Isolate shutdown");
          }
        }
      }
    }
  }
}

void Isolate::LowLevelShutdown() {
  // Ensure we have a zone and handle scope so that we can call VM functions,
  // but we no longer allocate new heap objects.
  Thread* thread = Thread::Current();
  StackZone stack_zone(thread);
  HandleScope handle_scope(thread);
  NoSafepointScope no_safepoint_scope;

  // Notify exit listeners that this isolate is shutting down.
  if (group()->object_store() != nullptr) {
    const Error& error = Error::Handle(thread->sticky_error());
    if (error.IsNull() || !error.IsUnwindError() ||
        UnwindError::Cast(error).is_user_initiated()) {
      NotifyExitListeners();
    }
  }

  // Close all the ports owned by this isolate.
  PortMap::ClosePorts(message_handler());

  // Fail fast if anybody tries to post any more messages to this isolate.
  delete message_handler_;
  message_handler_ = nullptr;

  // Clean up any synchronous FFI callbacks registered with this isolate. Skip
  // if this isolate never registered any.
  if (ffi_callback_list_head_ != nullptr) {
    FfiCallbackMetadata::Instance()->DeleteAllCallbacks(
        &ffi_callback_list_head_);
  }

#if !defined(PRODUCT)
  if (FLAG_dump_megamorphic_stats) {
    MegamorphicCacheTable::PrintSizes(thread);
  }
  if (FLAG_dump_symbol_stats) {
    Symbols::DumpStats(group());
  }
  if (FLAG_trace_isolates) {
    group()->heap()->PrintSizes();
    OS::PrintErr(
        "[-] Stopping isolate:\n"
        "\tisolate:    %s\n",
        name());
  }
  if (FLAG_print_metrics) {
    LogBlock lb;
    OS::PrintErr("Printing metrics for %s\n", name());
#define ISOLATE_GROUP_METRIC_PRINT(type, variable, name, unit)                 \
  OS::PrintErr("%s\n", isolate_group_->Get##variable##Metric()->ToString());
    ISOLATE_GROUP_METRIC_LIST(ISOLATE_GROUP_METRIC_PRINT)
#undef ISOLATE_GROUP_METRIC_PRINT
#define ISOLATE_METRIC_PRINT(type, variable, name, unit)                       \
  OS::PrintErr("%s\n", metric_##variable##_.ToString());
    ISOLATE_METRIC_LIST(ISOLATE_METRIC_PRINT)
#undef ISOLATE_METRIC_PRINT
    OS::PrintErr("\n");
  }
#endif  // !defined(PRODUCT)
}

#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
void IsolateGroup::MaybeIncreaseReloadEveryNStackOverflowChecks() {
  if (FLAG_reload_every_back_off) {
    if (reload_every_n_stack_overflow_checks_ < 5000) {
      reload_every_n_stack_overflow_checks_ += 99;
    } else {
      const auto old_value = reload_every_n_stack_overflow_checks_;
      reload_every_n_stack_overflow_checks_ = old_value * old_value;
    }
    // Cap the value.
    if (reload_every_n_stack_overflow_checks_ > 1000000) {
      reload_every_n_stack_overflow_checks_ = 1000000;
    }
  }
}
#endif  // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)

void Isolate::set_forward_table_new(WeakTable* table) {
  std::unique_ptr<WeakTable> value(table);
  forward_table_new_ = std::move(value);
}
void Isolate::set_forward_table_old(WeakTable* table) {
  std::unique_ptr<WeakTable> value(table);
  forward_table_old_ = std::move(value);
}

void Isolate::Shutdown() {
  Thread* thread = Thread::Current();
  ASSERT(this == thread->isolate());

  // Don't allow anymore dart code to execution on this isolate.
  thread->ClearStackLimit();

  {
    StackZone zone(thread);
    ServiceIsolate::SendIsolateShutdownMessage();
#if !defined(PRODUCT)
    HandleScope handle_scope(thread);
    debugger()->Shutdown();
    Profiler::IsolateShutdown(thread);
#endif
  }

#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
  if (FLAG_check_reloaded && is_runnable() && !Isolate::IsSystemIsolate(this)) {
    if (!group()->HasAttemptedReload()) {
      FATAL(
          "Isolate did not reload before exiting and "
          "--check-reloaded is enabled.\n");
    }
  }
#endif  // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)

  // Then, proceed with low-level teardown.
  Isolate::UnMarkIsolateReady(this);

  // Ensure native finalizers are run before isolate has shutdown message is
  // sent. This way users can rely on the exit message that an isolate will not
  // run any Dart code anymore _and_ will not run any native finalizers anymore.
  RunAndCleanupFinalizersOnShutdown();

  // Post message before LowLevelShutdown that sends onExit message.
  // This ensures that exit message comes last.
  if (bequest_ != nullptr) {
    auto beneficiary = bequest_->beneficiary();
    auto handle = bequest_->TakeHandle();
    PortMap::PostMessage(
        Message::New(beneficiary, handle, Message::kNormalPriority));
    bequest_.reset();
  }

  LowLevelShutdown();

  // Now we can unregister from the thread, invoke cleanup callback, delete the
  // isolate (and possibly the isolate group).
  Isolate::LowLevelCleanup(this);
}

void Isolate::LowLevelCleanup(Isolate* isolate) {
#if !defined(DART_PRECOMPILED_RUNTIME)
  if (isolate->is_kernel_isolate()) {
    KernelIsolate::SetKernelIsolate(nullptr);
  }
#endif
  if (isolate->is_service_isolate()) {
    ServiceIsolate::SetServiceIsolate(nullptr);
  }

  // Cache these two fields, since they are no longer available after the
  // `delete isolate` further down.
  IsolateGroup* isolate_group = isolate->isolate_group_;
  Dart_IsolateCleanupCallback cleanup = isolate->on_cleanup_callback();
  auto callback_data = isolate->init_callback_data_;

  // From this point on the isolate is no longer visited by GC (which is ok,
  // since we're just going to delete it anyway).
  isolate_group->UnregisterIsolate(isolate);

  // From this point on the isolate doesn't participate in safepointing
  // requests anymore.
  ASSERT(!Thread::Current()->HasActiveState());
  Thread::ExitIsolate(/*isolate_shutdown=*/true);

  // Now it's safe to delete the isolate.
  delete isolate;

  // Run isolate specific cleanup function for all non "vm-isolate's.
  const bool is_vm_isolate = Dart::vm_isolate() == isolate;
  if (!is_vm_isolate) {
    if (cleanup != nullptr) {
      cleanup(isolate_group->embedder_data(), callback_data);
    }
  }

  const bool shutdown_group = isolate_group->UnregisterIsolateDecrementCount();
  if (shutdown_group) {
    KernelIsolate::NotifyAboutIsolateGroupShutdown(isolate_group);

    if (!is_vm_isolate) {
      Thread::EnterIsolateGroupAsHelper(isolate_group, Thread::kUnknownTask,
                                        /*bypass_safepoint=*/false);
#if !defined(DART_PRECOMPILED_RUNTIME)
      BackgroundCompiler::Stop(isolate_group);
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

      // Finalize any weak persistent handles with a non-null referent with
      // isolate group still being available.
      FinalizeWeakPersistentHandlesVisitor visitor(isolate_group);
      isolate_group->api_state()->VisitWeakHandlesUnlocked(&visitor);

      Thread::ExitIsolateGroupAsHelper(/*bypass_safepoint=*/false);
    }

    // The "vm-isolate" does not have a thread pool.
    ASSERT(is_vm_isolate == (isolate_group->thread_pool() == nullptr));
    if (is_vm_isolate ||
        !isolate_group->thread_pool()->CurrentThreadIsWorker()) {
      isolate_group->Shutdown();
    } else {
      class ShutdownGroupTask : public ThreadPool::Task {
       public:
        explicit ShutdownGroupTask(IsolateGroup* isolate_group)
            : isolate_group_(isolate_group) {}

        virtual void Run() { isolate_group_->Shutdown(); }

       private:
        IsolateGroup* isolate_group_;
      };
      // The current thread is running on the isolate group's thread pool.
      // So we cannot safely delete the isolate group (and it's pool).
      // Instead we will destroy the isolate group on the VM-global pool.
      if (FLAG_trace_shutdown) {
        OS::PrintErr("[+%" Pd64 "ms] : Scheduling shutdown on VM pool %s\n",
                     Dart::UptimeMillis(), isolate_group->source()->name);
      }
      Dart::thread_pool()->Run<ShutdownGroupTask>(isolate_group);
    }
  } else {
    // TODO(dartbug.com/36097): An isolate just died. A significant amount of
    // memory might have become unreachable. We should evaluate how to best
    // inform the GC about this situation.
  }
}

Dart_InitializeIsolateCallback Isolate::initialize_callback_ = nullptr;
Dart_IsolateGroupCreateCallback Isolate::create_group_callback_ = nullptr;
Dart_IsolateShutdownCallback Isolate::shutdown_callback_ = nullptr;
Dart_IsolateCleanupCallback Isolate::cleanup_callback_ = nullptr;
Dart_IsolateGroupCleanupCallback Isolate::cleanup_group_callback_ = nullptr;
Dart_RegisterKernelBlobCallback Isolate::register_kernel_blob_callback_ =
    nullptr;
Dart_UnregisterKernelBlobCallback Isolate::unregister_kernel_blob_callback_ =
    nullptr;

Random* IsolateGroup::isolate_group_random_ = nullptr;
Monitor* Isolate::isolate_creation_monitor_ = nullptr;
bool Isolate::creation_enabled_ = false;

RwLock* IsolateGroup::isolate_groups_rwlock_ = nullptr;
IntrusiveDList<IsolateGroup>* IsolateGroup::isolate_groups_ = nullptr;

void Isolate::VisitObjectPointers(ObjectPointerVisitor* visitor,
                                  ValidationPolicy validate_frames) {
  ASSERT(visitor != nullptr);

  // Visit objects in the field table.
  // N.B.: The heap snapshot writer requires visiting the field table first, so
  // that the pointer visitation order aligns with order of field name metadata.
  if (!visitor->trace_values_through_fields()) {
    field_table()->VisitObjectPointers(visitor);
  }

  // Visit objects in the isolate object store.
  if (isolate_object_store() != nullptr) {
    isolate_object_store()->VisitObjectPointers(visitor);
  }

  visitor->clear_gc_root_type();
  // Visit the objects directly referenced from the isolate structure.
  visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(&current_tag_));
  visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(&default_tag_));
  visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(&tag_table_));
  visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(&sticky_error_));
  visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(&finalizers_));
#if !defined(PRODUCT)
  visitor->VisitPointer(
      reinterpret_cast<ObjectPtr*>(&pending_service_extension_calls_));
  visitor->VisitPointer(
      reinterpret_cast<ObjectPtr*>(&registered_service_extension_handlers_));
#endif  // !defined(PRODUCT)

#if !defined(PRODUCT)
  // Visit objects in the debugger.
  if (debugger() != nullptr) {
    debugger()->VisitObjectPointers(visitor);
  }
  if (is_service_isolate()) {
    ServiceIsolate::VisitObjectPointers(visitor);
  }
#endif  // !defined(PRODUCT)

#if !defined(DART_PRECOMPILED_RUNTIME)
  // Visit objects that are being used for deoptimization.
  if (deopt_context() != nullptr) {
    deopt_context()->VisitObjectPointers(visitor);
  }
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

  visitor->VisitPointer(
      reinterpret_cast<ObjectPtr*>(&loaded_prefixes_set_storage_));

  if (pointers_to_verify_at_exit_.length() != 0) {
    visitor->VisitPointers(&pointers_to_verify_at_exit_[0],
                           pointers_to_verify_at_exit_.length());
  }
}

void Isolate::VisitStackPointers(ObjectPointerVisitor* visitor,
                                 ValidationPolicy validate_frames) {
  if (mutator_thread_ != nullptr) {
    mutator_thread_->VisitObjectPointers(visitor, validate_frames);
  }
}

void IsolateGroup::ReleaseStoreBuffers() {
  thread_registry()->ReleaseStoreBuffers();
}

void IsolateGroup::FlushMarkingStacks() {
  thread_registry()->FlushMarkingStacks();
}

void Isolate::RememberLiveTemporaries() {
  if (mutator_thread_ != nullptr) {
    mutator_thread_->RememberLiveTemporaries();
  }
}

void Isolate::DeferredMarkLiveTemporaries() {
  if (mutator_thread_ != nullptr) {
    mutator_thread_->DeferredMarkLiveTemporaries();
  }
}

void Isolate::init_loaded_prefixes_set_storage() {
  ASSERT(loaded_prefixes_set_storage_ == nullptr);
  loaded_prefixes_set_storage_ =
      HashTables::New<UnorderedHashSet<LibraryPrefixMapTraits> >(4);
}

bool Isolate::IsPrefixLoaded(const LibraryPrefix& prefix) const {
  UnorderedHashSet<LibraryPrefixMapTraits> loaded_prefixes_set(
      loaded_prefixes_set_storage_);
  bool result = loaded_prefixes_set.GetOrNull(prefix) != Object::null();
  loaded_prefixes_set.Release();
  return result;
}

void Isolate::SetPrefixIsLoaded(const LibraryPrefix& prefix) {
  UnorderedHashSet<LibraryPrefixMapTraits> loaded_prefixes_set(
      loaded_prefixes_set_storage_);
  loaded_prefixes_set.InsertOrGet(prefix);
  loaded_prefixes_set_storage_ = loaded_prefixes_set.Release().ptr();
}

void IsolateGroup::EnableIncrementalBarrier(
    MarkingStack* old_marking_stack,
    MarkingStack* new_marking_stack,
    MarkingStack* deferred_marking_stack) {
  ASSERT(old_marking_stack_ == nullptr);
  old_marking_stack_ = old_marking_stack;
  ASSERT(new_marking_stack_ == nullptr);
  new_marking_stack_ = new_marking_stack;
  ASSERT(deferred_marking_stack_ == nullptr);
  deferred_marking_stack_ = deferred_marking_stack;
  thread_registry()->AcquireMarkingStacks();
  ASSERT(Thread::Current()->is_marking());
}

void IsolateGroup::DisableIncrementalBarrier() {
  thread_registry()->ReleaseMarkingStacks();
  ASSERT(old_marking_stack_ != nullptr);
  old_marking_stack_ = nullptr;
  ASSERT(new_marking_stack_ != nullptr);
  new_marking_stack_ = nullptr;
  ASSERT(deferred_marking_stack_ != nullptr);
  deferred_marking_stack_ = nullptr;
}

void IsolateGroup::ForEachIsolate(
    std::function<void(Isolate* isolate)> function,
    bool at_safepoint) {
  auto thread = Thread::Current();
  if (at_safepoint) {
    ASSERT(thread->OwnsSafepoint() ||
           (thread->task_kind() == Thread::kMutatorTask) ||
           (thread->task_kind() == Thread::kMarkerTask) ||
           (thread->task_kind() == Thread::kCompactorTask) ||
           (thread->task_kind() == Thread::kScavengerTask) ||
           (thread->task_kind() == Thread::kIncrementalCompactorTask));
    for (Isolate* isolate : isolates_) {
      function(isolate);
    }
    return;
  }
  if (thread != nullptr && thread->OwnsSafepoint()) {
    for (Isolate* isolate : isolates_) {
      function(isolate);
    }
    return;
  }
  SafepointReadRwLocker ml(thread, isolates_lock_.get());
  for (Isolate* isolate : isolates_) {
    function(isolate);
  }
}

Isolate* IsolateGroup::FirstIsolate() const {
  SafepointReadRwLocker ml(Thread::Current(), isolates_lock_.get());
  return FirstIsolateLocked();
}

Isolate* IsolateGroup::FirstIsolateLocked() const {
  return isolates_.IsEmpty() ? nullptr : isolates_.First();
}

void IsolateGroup::RunWithStoppedMutatorsCallable(
    Callable* single_current_mutator,
    Callable* otherwise,
    bool use_force_growth_in_otherwise) {
  auto thread = Thread::Current();
  StoppedMutatorsScope stopped_mutators_scope(thread);

  if (thread->OwnsSafepoint()) {
    RELEASE_ASSERT(thread->OwnsSafepoint());
    single_current_mutator->Call();
    return;
  }

  {
    SafepointReadRwLocker ml(thread, isolates_lock_.get());
    if (thread->IsDartMutatorThread() && ContainsOnlyOneIsolate()) {
      single_current_mutator->Call();
      return;
    }
  }

  // We use the more strict safepoint operation scope here (which ensures that
  // all other threads, including auxiliary threads are at a safepoint), even
  // though we only need to ensure that the mutator threads are stopped.
  if (use_force_growth_in_otherwise) {
    ForceGrowthSafepointOperationScope safepoint_scope(
        thread, SafepointLevel::kGCAndDeopt);
    otherwise->Call();
  } else {
    DeoptSafepointOperationScope safepoint_scope(thread);
    otherwise->Call();
  }
}

void IsolateGroup::VisitObjectPointers(ObjectPointerVisitor* visitor,
                                       ValidationPolicy validate_frames) {
  VisitSharedPointers(visitor);
  for (Isolate* isolate : isolates_) {
    isolate->VisitObjectPointers(visitor, validate_frames);
  }
  VisitStackPointers(visitor, validate_frames);
}

void IsolateGroup::VisitSharedPointers(ObjectPointerVisitor* visitor) {
  // Visit objects in the class table.
  class_table()->VisitObjectPointers(visitor);
  if (heap_walk_class_table() != class_table()) {
    heap_walk_class_table()->VisitObjectPointers(visitor);
  }
  api_state()->VisitObjectPointersUnlocked(visitor);
  // Visit objects in the object store.
  if (object_store() != nullptr) {
    object_store()->VisitObjectPointers(visitor);
  }
  visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(&saved_unlinked_calls_));
  initial_field_table()->VisitObjectPointers(visitor);
  shared_initial_field_table()->VisitObjectPointers(visitor);
  shared_field_table()->VisitObjectPointers(visitor);

  // Visit the boxed_field_list_.
  // 'boxed_field_list_' access via mutator and background compilation threads
  // is guarded with a monitor. This means that we can visit it only
  // when at safepoint or the field_list_mutex_ lock has been taken.
  visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(&boxed_field_list_));

  NOT_IN_PRECOMPILED(background_compiler()->VisitPointers(visitor));

#if !defined(PRODUCT)
  if (debugger() != nullptr) {
    debugger()->VisitObjectPointers(visitor);
  }
#endif

#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
  // Visit objects that are being used for isolate reload.
  if (program_reload_context() != nullptr) {
    program_reload_context()->VisitObjectPointers(visitor);
    program_reload_context()->group_reload_context()->VisitObjectPointers(
        visitor);
  }
#endif  // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)

  if (source()->loaded_blobs_ != nullptr) {
    visitor->VisitPointer(
        reinterpret_cast<ObjectPtr*>(&(source()->loaded_blobs_)));
  }

  if (become() != nullptr) {
    become()->VisitObjectPointers(visitor);
  }
}

void IsolateGroup::VisitStackPointers(ObjectPointerVisitor* visitor,
                                      ValidationPolicy validate_frames) {
  visitor->set_gc_root_type("stack");

  // Visit objects in all threads (e.g. Dart stack, handles in zones), except
  // for the mutator threads themselves.
  thread_registry()->VisitObjectPointers(this, visitor, validate_frames);

  for (Isolate* isolate : isolates_) {
    // Visit mutator thread, even if the isolate isn't entered/scheduled
    // (there might be live API handles to visit).
    isolate->VisitStackPointers(visitor, validate_frames);
  }

  visitor->clear_gc_root_type();
}

void IsolateGroup::VisitPointersInAllServiceIdZones(
    ObjectPointerVisitor& visitor) {
#if !defined(PRODUCT)
  for (Isolate* isolate : isolates_) {
    for (intptr_t i = 0; i < isolate->NumServiceIdZones(); ++i) {
      isolate->GetServiceIdZone(i)->VisitPointers(visitor);
    }
  }
#endif  // !defined(PRODUCT)
}

void IsolateGroup::VisitWeakPersistentHandles(HandleVisitor* visitor) {
  api_state()->VisitWeakHandlesUnlocked(visitor);
}

void IsolateGroup::DeferredMarkLiveTemporaries() {
  ForEachIsolate(
      [&](Isolate* isolate) { isolate->DeferredMarkLiveTemporaries(); },
      /*at_safepoint=*/true);
}

void IsolateGroup::RememberLiveTemporaries() {
  ForEachIsolate([&](Isolate* isolate) { isolate->RememberLiveTemporaries(); },
                 /*at_safepoint=*/true);
}

#if !defined(PRODUCT)
RingServiceIdZone& Isolate::AddServiceIdZone(
    ObjectIdRing::BackingBufferKind backing_buffer_kind,
    ObjectIdRing::IdPolicy id_assignment_policy,
    int32_t capacity) {
  EnsureDefaultServiceIdZone();
  switch (backing_buffer_kind) {
    case ObjectIdRing::BackingBufferKind::kRing:
      service_id_zones_->Add(new RingServiceIdZone(
          service_id_zones_->length(), id_assignment_policy, capacity));
      return *service_id_zones_->Last();
    default:
      UNREACHABLE();
  }
}

void Isolate::DeleteServiceIdZone(int32_t id) {
  ASSERT(service_id_zones_ != nullptr);
  ASSERT(id < service_id_zones_->length());
  delete service_id_zones_->At(id);
  (*service_id_zones_)[id] = nullptr;
}

RingServiceIdZone& Isolate::EnsureDefaultServiceIdZone() {
  if (service_id_zones_ == nullptr) {
    service_id_zones_ = new MallocGrowableArray<RingServiceIdZone*>();
  }
  if (service_id_zones_->is_empty()) {
    service_id_zones_->Add(
        new RingServiceIdZone(0, ObjectIdRing::IdPolicy::kAllocateId,
                              RingServiceIdZone::kDefaultCapacity));
  }
  return *service_id_zones_->At(0);
}

RingServiceIdZone* Isolate::GetServiceIdZone(intptr_t zone_id) const {
  if (service_id_zones_ == nullptr || service_id_zones_->length() <= zone_id) {
    return nullptr;
  }
  return service_id_zones_->At(zone_id);
}

intptr_t Isolate::NumServiceIdZones() const {
  if (service_id_zones_ == nullptr) {
    return 0;
  }
  return service_id_zones_->length();
}

static const char* ExceptionPauseInfoToServiceEnum(Dart_ExceptionPauseInfo pi) {
  switch (pi) {
    case kPauseOnAllExceptions:
      return "All";
    case kNoPauseOnExceptions:
      return "None";
    case kPauseOnUnhandledExceptions:
      return "Unhandled";
    default:
      UNIMPLEMENTED();
      return nullptr;
  }
}

static ServiceEvent IsolatePauseEvent(Isolate* isolate) {
  if (!isolate->is_runnable()) {
    // Isolate is not yet runnable.
    ASSERT((isolate->debugger() == nullptr) ||
           (isolate->debugger()->PauseEvent() == nullptr));
    return ServiceEvent(isolate, ServiceEvent::kNone);
  } else if (isolate->message_handler()->should_pause_on_start()) {
    if (isolate->message_handler()->is_paused_on_start()) {
      ASSERT((isolate->debugger() == nullptr) ||
             (isolate->debugger()->PauseEvent() == nullptr));
      return ServiceEvent(isolate, ServiceEvent::kPauseStart);
    } else {
      // Isolate is runnable but not paused on start.
      // Some service clients get confused if they see:
      // NotRunnable -> Runnable -> PausedAtStart
      // Treat Runnable+ShouldPauseOnStart as NotRunnable so they see:
      // NonRunnable -> PausedAtStart
      // The should_pause_on_start flag is set to false after resume.
      ASSERT((isolate->debugger() == nullptr) ||
             (isolate->debugger()->PauseEvent() == nullptr));
      return ServiceEvent(isolate, ServiceEvent::kNone);
    }
  } else if (isolate->message_handler()->is_paused_on_exit() &&
             ((isolate->debugger() == nullptr) ||
              (isolate->debugger()->PauseEvent() == nullptr))) {
    return ServiceEvent(isolate, ServiceEvent::kPauseExit);
  } else if ((isolate->debugger() != nullptr) &&
             (isolate->debugger()->PauseEvent() != nullptr) &&
             !isolate->ResumeRequest()) {
    return *(isolate->debugger()->PauseEvent());
  } else {
    ServiceEvent pause_event(isolate, ServiceEvent::kResume);

#if !defined(DART_PRECOMPILED_RUNTIME)
    if (isolate->debugger() != nullptr) {
      // TODO(turnidge): Don't compute a full stack trace.
      DebuggerStackTrace* stack = isolate->debugger()->StackTrace();
      if (stack->Length() > 0) {
        pause_event.set_top_frame(stack->FrameAt(0));
      }
    }
#endif

    return pause_event;
  }
}

void Isolate::PrintJSON(JSONStream* stream, bool ref) {
  JSONObject jsobj(stream);
  jsobj.AddProperty("type", (ref ? "@Isolate" : "Isolate"));
  jsobj.AddServiceId(ISOLATE_SERVICE_ID_FORMAT_STRING,
                     static_cast<int64_t>(main_port()));

  jsobj.AddProperty("name", name());
  jsobj.AddPropertyF("number", "%" Pd64 "", static_cast<int64_t>(main_port()));
  jsobj.AddProperty("isSystemIsolate", is_system_isolate());
  jsobj.AddPropertyF("isolateGroupId", ISOLATE_GROUP_SERVICE_ID_FORMAT_STRING,
                     group()->id());
  if (ref) {
    return;
  }
  jsobj.AddPropertyF("_originNumber", "%" Pd64 "",
                     static_cast<int64_t>(origin_id()));
  int64_t uptime_millis = UptimeMicros() / kMicrosecondsPerMillisecond;
  int64_t start_time = OS::GetCurrentTimeMillis() - uptime_millis;
  jsobj.AddPropertyTimeMillis("startTime", start_time);
  {
    JSONObject jsheap(&jsobj, "_heaps");
    group()->heap()->PrintToJSONObject(Heap::kNew, &jsheap);
    group()->heap()->PrintToJSONObject(Heap::kOld, &jsheap);
  }

  {
// Stringification macros
// See https://gcc.gnu.org/onlinedocs/gcc-4.8.5/cpp/Stringification.html
#define TO_STRING(s) STR(s)
#define STR(s) #s

#define ADD_ISOLATE_FLAGS(when, name, bitname, isolate_flag_name, flag_name)   \
  {                                                                            \
    JSONObject jsflag(&jsflags);                                               \
    jsflag.AddProperty("name", TO_STRING(name));                               \
    jsflag.AddProperty("valueAsString", name() ? "true" : "false");            \
  }
    JSONArray jsflags(&jsobj, "isolateFlags");
    BOOL_ISOLATE_FLAG_LIST(ADD_ISOLATE_FLAGS)
#undef ADD_ISOLATE_FLAGS
#undef TO_STRING
#undef STR
  }

  jsobj.AddProperty("runnable", is_runnable());
  jsobj.AddProperty("livePorts", open_ports_keepalive_);
  jsobj.AddProperty("pauseOnExit", message_handler()->should_pause_on_exit());
#if !defined(DART_PRECOMPILED_RUNTIME)
  jsobj.AddProperty("_isReloading", group()->IsReloading());
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

  ServiceEvent pause_event = IsolatePauseEvent(this);
  jsobj.AddProperty("pauseEvent", &pause_event);

  const Library& lib = Library::Handle(group()->object_store()->root_library());
  if (!lib.IsNull()) {
    jsobj.AddProperty("rootLib", lib);
  }

  if (FLAG_profiler) {
    JSONObject tagCounters(&jsobj, "_tagCounters");
    vm_tag_counters()->PrintToJSONObject(&tagCounters);
  }
  if (Thread::Current()->sticky_error() != Object::null()) {
    Error& error = Error::Handle(Thread::Current()->sticky_error());
    ASSERT(!error.IsNull());
    jsobj.AddProperty("error", error, false);
  } else if (sticky_error() != Object::null()) {
    Error& error = Error::Handle(sticky_error());
    ASSERT(!error.IsNull());
    jsobj.AddProperty("error", error, false);
  }

  {
    const GrowableObjectArray& libs =
        GrowableObjectArray::Handle(group()->object_store()->libraries());
    intptr_t num_libs = libs.Length();
    Library& lib = Library::Handle();

    JSONArray lib_array(&jsobj, "libraries");
    for (intptr_t i = 0; i < num_libs; i++) {
      lib ^= libs.At(i);
      ASSERT(!lib.IsNull());
      lib_array.AddValue(lib);
    }
  }

  {
    JSONArray breakpoints(&jsobj, "breakpoints");
    if (debugger() != nullptr) {
      debugger()->PrintBreakpointsToJSONArray(&breakpoints);
    }
  }

  Dart_ExceptionPauseInfo pause_info = (debugger() != nullptr)
                                           ? debugger()->GetExceptionPauseInfo()
                                           : kNoPauseOnExceptions;
  jsobj.AddProperty("exceptionPauseMode",
                    ExceptionPauseInfoToServiceEnum(pause_info));

  if (debugger() != nullptr) {
    JSONObject settings(&jsobj, "_debuggerSettings");
    debugger()->PrintSettingsToJSONObject(&settings);
  }

  {
    GrowableObjectArray& handlers =
        GrowableObjectArray::Handle(registered_service_extension_handlers());
    if (!handlers.IsNull()) {
      JSONArray extensions(&jsobj, "extensionRPCs");
      String& handler_name = String::Handle();
      for (intptr_t i = 0; i < handlers.Length(); i += kRegisteredEntrySize) {
        handler_name ^= handlers.At(i + kRegisteredNameIndex);
        extensions.AddValue(handler_name.ToCString());
      }
    }
  }

  {
    JSONObject isolate_group(&jsobj, "isolate_group");
    group()->PrintToJSONObject(&isolate_group, /*ref=*/true);
  }
}

void Isolate::PrintMemoryUsageJSON(JSONStream* stream) {
  group()->heap()->PrintMemoryUsageJSON(stream);
}

void Isolate::PrintPauseEventJSON(JSONStream* stream) {
  IsolatePauseEvent(this).PrintJSON(stream);
}

#endif  // !defined(PRODUCT)

void Isolate::set_tag_table(const GrowableObjectArray& value) {
  tag_table_ = value.ptr();
}

void Isolate::set_current_tag(const UserTag& tag) {
  uword user_tag = tag.tag();
  ASSERT(user_tag < kUwordMax);
  set_user_tag(user_tag);
  current_tag_ = tag.ptr();
}

void Isolate::set_default_tag(const UserTag& tag) {
  default_tag_ = tag.ptr();
}

ErrorPtr Isolate::StealStickyError() {
  NoSafepointScope no_safepoint;
  ErrorPtr return_value = sticky_error_;
  sticky_error_ = Error::null();
  return return_value;
}

#if !defined(PRODUCT)
void Isolate::set_pending_service_extension_calls(
    const GrowableObjectArray& value) {
  pending_service_extension_calls_ = value.ptr();
}

void Isolate::set_registered_service_extension_handlers(
    const GrowableObjectArray& value) {
  registered_service_extension_handlers_ = value.ptr();
}

ErrorPtr Isolate::InvokePendingServiceExtensionCalls() {
  GrowableObjectArray& calls =
      GrowableObjectArray::Handle(GetAndClearPendingServiceExtensionCalls());
  if (calls.IsNull()) {
    return Error::null();
  }
  // Grab run function.
  const Library& developer_lib = Library::Handle(Library::DeveloperLibrary());
  ASSERT(!developer_lib.IsNull());
  const Function& run_extension = Function::Handle(
      developer_lib.LookupFunctionAllowPrivate(Symbols::_runExtension()));
  ASSERT(!run_extension.IsNull());

  const Array& arguments =
      Array::Handle(Array::New(kPendingEntrySize + 1, Heap::kNew));
  Object& result = Object::Handle();
  String& method_name = String::Handle();
  Instance& closure = Instance::Handle();
  Array& parameter_keys = Array::Handle();
  Array& parameter_values = Array::Handle();
  Instance& reply_port = Instance::Handle();
  Instance& id = Instance::Handle();
  for (intptr_t i = 0; i < calls.Length(); i += kPendingEntrySize) {
    // Grab arguments for call.
    closure ^= calls.At(i + kPendingHandlerIndex);
    ASSERT(!closure.IsNull());
    arguments.SetAt(kPendingHandlerIndex, closure);
    method_name ^= calls.At(i + kPendingMethodNameIndex);
    ASSERT(!method_name.IsNull());
    arguments.SetAt(kPendingMethodNameIndex, method_name);
    parameter_keys ^= calls.At(i + kPendingKeysIndex);
    ASSERT(!parameter_keys.IsNull());
    arguments.SetAt(kPendingKeysIndex, parameter_keys);
    parameter_values ^= calls.At(i + kPendingValuesIndex);
    ASSERT(!parameter_values.IsNull());
    arguments.SetAt(kPendingValuesIndex, parameter_values);
    reply_port ^= calls.At(i + kPendingReplyPortIndex);
    ASSERT(!reply_port.IsNull());
    arguments.SetAt(kPendingReplyPortIndex, reply_port);
    id ^= calls.At(i + kPendingIdIndex);
    arguments.SetAt(kPendingIdIndex, id);
    arguments.SetAt(kPendingEntrySize, Bool::Get(FLAG_trace_service));

    if (FLAG_trace_service) {
      OS::PrintErr("[+%" Pd64 "ms] Isolate %s invoking _runExtension for %s\n",
                   Dart::UptimeMillis(), name(), method_name.ToCString());
    }
    result = DartEntry::InvokeFunction(run_extension, arguments);
    if (FLAG_trace_service) {
      OS::PrintErr("[+%" Pd64 "ms] Isolate %s _runExtension complete for %s\n",
                   Dart::UptimeMillis(), name(), method_name.ToCString());
    }
    // Propagate the error.
    if (result.IsError()) {
      // Remaining service extension calls are dropped.
      if (!result.IsUnwindError()) {
        // Send error back over the protocol.
        Service::PostError(method_name, parameter_keys, parameter_values,
                           reply_port, id, Error::Cast(result));
      }
      return Error::Cast(result).ptr();
    }
    // Drain the microtask queue.
    result = DartLibraryCalls::DrainMicrotaskQueue();
    // Propagate the error.
    if (result.IsError()) {
      // Remaining service extension calls are dropped.
      return Error::Cast(result).ptr();
    }
  }
  return Error::null();
}

GrowableObjectArrayPtr Isolate::GetAndClearPendingServiceExtensionCalls() {
  GrowableObjectArrayPtr r = pending_service_extension_calls_;
  pending_service_extension_calls_ = GrowableObjectArray::null();
  return r;
}

void Isolate::AppendServiceExtensionCall(const Instance& closure,
                                         const String& method_name,
                                         const Array& parameter_keys,
                                         const Array& parameter_values,
                                         const Instance& reply_port,
                                         const Instance& id) {
  if (FLAG_trace_service) {
    OS::PrintErr("[+%" Pd64
                 "ms] Isolate %s ENQUEUING request for extension %s\n",
                 Dart::UptimeMillis(), name(), method_name.ToCString());
  }
  GrowableObjectArray& calls =
      GrowableObjectArray::Handle(pending_service_extension_calls());
  bool schedule_drain = false;
  if (calls.IsNull()) {
    calls = GrowableObjectArray::New();
    ASSERT(!calls.IsNull());
    set_pending_service_extension_calls(calls);
    schedule_drain = true;
  }
  ASSERT(kPendingHandlerIndex == 0);
  calls.Add(closure);
  ASSERT(kPendingMethodNameIndex == 1);
  calls.Add(method_name);
  ASSERT(kPendingKeysIndex == 2);
  calls.Add(parameter_keys);
  ASSERT(kPendingValuesIndex == 3);
  calls.Add(parameter_values);
  ASSERT(kPendingReplyPortIndex == 4);
  calls.Add(reply_port);
  ASSERT(kPendingIdIndex == 5);
  calls.Add(id);

  if (schedule_drain) {
    const Array& msg = Array::Handle(Array::New(3));
    Object& element = Object::Handle();
    element = Smi::New(Message::kIsolateLibOOBMsg);
    msg.SetAt(0, element);
    element = Smi::New(Isolate::kDrainServiceExtensionsMsg);
    msg.SetAt(1, element);
    element = Smi::New(Isolate::kBeforeNextEventAction);
    msg.SetAt(2, element);
    std::unique_ptr<Message> message = WriteMessage(
        /* same_group */ false, msg, main_port(), Message::kOOBPriority);
    bool posted = PortMap::PostMessage(std::move(message));
    ASSERT(posted);
  }
}

// This function is written in C++ and not Dart because we must do this
// operation atomically in the face of random OOB messages. Do not port
// to Dart code unless you can ensure that the operations will can be
// done atomically.
void Isolate::RegisterServiceExtensionHandler(const String& name,
                                              const Instance& closure) {
  // Don't allow for service extensions to be registered for internal isolates.
  if (Isolate::IsVMInternalIsolate(this)) {
    return;
  }
  GrowableObjectArray& handlers =
      GrowableObjectArray::Handle(registered_service_extension_handlers());
  if (handlers.IsNull()) {
    handlers = GrowableObjectArray::New(Heap::kOld);
    set_registered_service_extension_handlers(handlers);
  }
#if defined(DEBUG)
  {
    // Sanity check.
    const Instance& existing_handler =
        Instance::Handle(LookupServiceExtensionHandler(name));
    ASSERT(existing_handler.IsNull());
  }
#endif
  ASSERT(kRegisteredNameIndex == 0);
  handlers.Add(name, Heap::kOld);
  ASSERT(kRegisteredHandlerIndex == 1);
  handlers.Add(closure, Heap::kOld);
  {
    // Fire off an event.
    ServiceEvent event(this, ServiceEvent::kServiceExtensionAdded);
    event.set_extension_rpc(&name);
    Service::HandleEvent(&event);
  }
}

// This function is written in C++ and not Dart because we must do this
// operation atomically in the face of random OOB messages. Do not port
// to Dart code unless you can ensure that the operations will can be
// done atomically.
InstancePtr Isolate::LookupServiceExtensionHandler(const String& name) {
  const GrowableObjectArray& handlers =
      GrowableObjectArray::Handle(registered_service_extension_handlers());
  if (handlers.IsNull()) {
    return Instance::null();
  }
  String& handler_name = String::Handle();
  for (intptr_t i = 0; i < handlers.Length(); i += kRegisteredEntrySize) {
    handler_name ^= handlers.At(i + kRegisteredNameIndex);
    ASSERT(!handler_name.IsNull());
    if (handler_name.Equals(name)) {
      return Instance::RawCast(handlers.At(i + kRegisteredHandlerIndex));
    }
  }
  return Instance::null();
}

void Isolate::WakePauseEventHandler(Dart_Isolate isolate) {
  Isolate* iso = reinterpret_cast<Isolate*>(isolate);
  MonitorLocker ml(iso->pause_loop_monitor_);
  ml.Notify();

  Dart_MessageNotifyCallback current_notify_callback =
      iso->message_notify_callback();
  // It is possible that WakePauseEventHandler was replaced by original callback
  // while waiting for pause_loop_monitor_. In that case PauseEventHandler
  // is no longer running and the original callback needs to be invoked instead
  // of incrementing wake_pause_event_handler_count_.
  if (current_notify_callback != Isolate::WakePauseEventHandler) {
    if (current_notify_callback != nullptr) {
      current_notify_callback(isolate);
    }
  } else {
    ++iso->wake_pause_event_handler_count_;
  }
}

void Isolate::PauseEventHandler() {
  // We are stealing a pause event (like a breakpoint) from the
  // embedder.  We don't know what kind of thread we are on -- it
  // could be from our thread pool or it could be a thread from the
  // embedder.  Sit on the current thread handling service events
  // until we are told to resume.
  if (pause_loop_monitor_ == nullptr) {
    pause_loop_monitor_ = new Monitor();
  }
  Dart_EnterScope();
  MonitorLocker ml(pause_loop_monitor_, false);

  Dart_MessageNotifyCallback saved_notify_callback = message_notify_callback();
  ASSERT(wake_pause_event_handler_count_ == 0);
  set_message_notify_callback(Isolate::WakePauseEventHandler);

#if !defined(DART_PRECOMPILED_RUNTIME)
  const bool had_program_reload_context =
      group()->program_reload_context() != nullptr;
  const int64_t start_time_micros = !had_program_reload_context
                                        ? 0
                                        : group()
                                              ->program_reload_context()
                                              ->group_reload_context()
                                              ->start_time_micros();
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
  bool resume = false;
  while (true) {
    // Handle all available vm service messages, up to a resume
    // request.
    while (!resume && Dart_HasServiceMessages()) {
      ml.Exit();
      resume = Dart_HandleServiceMessages();
      ml.Enter();
    }
    if (resume) {
      break;
    }

#if !defined(DART_PRECOMPILED_RUNTIME)
    if (had_program_reload_context &&
        (group()->program_reload_context() == nullptr)) {
      if (FLAG_trace_reload) {
        const int64_t reload_time_micros =
            OS::GetCurrentMonotonicMicros() - start_time_micros;
        double reload_millis = MicrosecondsToMilliseconds(reload_time_micros);
        OS::PrintErr("Reloading has finished! (%.2f ms)\n", reload_millis);
      }
      break;
    }
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

    // Wait for more service messages.
    Monitor::WaitResult res = ml.Wait();
    ASSERT(res == Monitor::kNotified);
  }
  // If any non-service messages came in, we need to notify the registered
  // message notify callback to check for unhandled messages. Otherwise, events
  // may be left unhandled until the next event comes in. See
  // https://github.com/dart-lang/sdk/issues/37312.
  if (saved_notify_callback != nullptr) {
    while (wake_pause_event_handler_count_ > 0) {
      saved_notify_callback(Api::CastIsolate(this));
      --wake_pause_event_handler_count_;
    }
  } else {
    wake_pause_event_handler_count_ = 0;
  }
  set_message_notify_callback(saved_notify_callback);
  Dart_ExitScope();
}
#endif  // !defined(PRODUCT)

void Isolate::VisitIsolates(IsolateVisitor* visitor) {
  if (visitor == nullptr) {
    return;
  }
  IsolateGroup::ForEach([&](IsolateGroup* group) {
    group->ForEachIsolate(
        [&](Isolate* isolate) { visitor->VisitIsolate(isolate); });
  });
}

intptr_t Isolate::IsolateListLength() {
  intptr_t count = 0;
  IsolateGroup::ForEach([&](IsolateGroup* group) {
    group->ForEachIsolate([&](Isolate* isolate) { count++; });
  });
  return count;
}

Isolate* Isolate::LookupIsolateByPort(Dart_Port port) {
  Isolate* match = nullptr;
  IsolateGroup::ForEach([&](IsolateGroup* group) {
    group->ForEachIsolate([&](Isolate* isolate) {
      if (isolate->main_port() == port) {
        match = isolate;
      }
    });
  });
  return match;
}

std::unique_ptr<char[]> Isolate::LookupIsolateNameByPort(Dart_Port port) {
  MonitorLocker ml(isolate_creation_monitor_);
  std::unique_ptr<char[]> result;
  IsolateGroup::ForEach([&](IsolateGroup* group) {
    group->ForEachIsolate([&](Isolate* isolate) {
      if (isolate->main_port() == port) {
        const size_t len = strlen(isolate->name()) + 1;
        result = std::unique_ptr<char[]>(new char[len]);
        strncpy(result.get(), isolate->name(), len);
      }
    });
  });
  return result;
}

bool Isolate::TryMarkIsolateReady(Isolate* isolate) {
  MonitorLocker ml(isolate_creation_monitor_);
  if (!creation_enabled_) {
    return false;
  }
  isolate->accepts_messages_ = true;
  return true;
}

void Isolate::UnMarkIsolateReady(Isolate* isolate) {
  MonitorLocker ml(isolate_creation_monitor_);
  isolate->accepts_messages_ = false;
}

void Isolate::DisableIsolateCreation() {
  MonitorLocker ml(isolate_creation_monitor_);
  creation_enabled_ = false;
}

void Isolate::EnableIsolateCreation() {
  MonitorLocker ml(isolate_creation_monitor_);
  creation_enabled_ = true;
}

bool Isolate::IsolateCreationEnabled() {
  MonitorLocker ml(isolate_creation_monitor_);
  return creation_enabled_;
}

bool IsolateGroup::IsSystemIsolateGroup(const IsolateGroup* group) {
  return group->source()->flags.is_system_isolate;
}

bool Isolate::IsVMInternalIsolate(const Isolate* isolate) {
  return isolate->is_kernel_isolate() || isolate->is_service_isolate() ||
         isolate->is_vm_isolate();
}

void Isolate::KillLocked(LibMsgId msg_id) {
  Dart_CObject kill_msg;
  Dart_CObject* list_values[4];
  kill_msg.type = Dart_CObject_kArray;
  kill_msg.value.as_array.length = 4;
  kill_msg.value.as_array.values = list_values;

  Dart_CObject oob;
  oob.type = Dart_CObject_kInt32;
  oob.value.as_int32 = Message::kIsolateLibOOBMsg;
  list_values[0] = &oob;

  Dart_CObject msg_type;
  msg_type.type = Dart_CObject_kInt32;
  msg_type.value.as_int32 = msg_id;
  list_values[1] = &msg_type;

  Dart_CObject cap;
  cap.type = Dart_CObject_kCapability;
  cap.value.as_capability.id = terminate_capability();
  list_values[2] = &cap;

  Dart_CObject imm;
  imm.type = Dart_CObject_kInt32;
  imm.value.as_int32 = Isolate::kImmediateAction;
  list_values[3] = &imm;

  {
    AllocOnlyStackZone zone;
    std::unique_ptr<Message> message = WriteApiMessage(
        zone.GetZone(), &kill_msg, main_port(), Message::kOOBPriority);
    ASSERT(message != nullptr);

    // Post the message at the given port.
    bool success = PortMap::PostMessage(std::move(message));
    ASSERT(success);
  }
}

class IsolateKillerVisitor : public IsolateVisitor {
 public:
  IsolateKillerVisitor(Isolate::LibMsgId msg_id,
                       bool kill_system_isolates = false)
      : target_(nullptr),
        msg_id_(msg_id),
        kill_system_isolates_(kill_system_isolates) {}

  IsolateKillerVisitor(Isolate* isolate, Isolate::LibMsgId msg_id)
      : target_(isolate), msg_id_(msg_id), kill_system_isolates_(false) {
    ASSERT(isolate != Dart::vm_isolate());
  }

  virtual ~IsolateKillerVisitor() {}

  void VisitIsolate(Isolate* isolate) {
    MonitorLocker ml(Isolate::isolate_creation_monitor_);
    ASSERT(isolate != nullptr);
    if (ShouldKill(isolate)) {
      if (isolate->AcceptsMessagesLocked()) {
        isolate->KillLocked(msg_id_);
      }
    }
  }

 private:
  bool ShouldKill(Isolate* isolate) {
    if (kill_system_isolates_) {
      ASSERT(target_ == nullptr);
      // Don't kill the service isolate or vm isolate.
      return IsSystemIsolate(isolate) && !Isolate::IsVMInternalIsolate(isolate);
    }
    // If a target_ is specified, then only kill the target_.
    // Otherwise, don't kill the service isolate or vm isolate.
    return (((target_ != nullptr) && (isolate == target_)) ||
            ((target_ == nullptr) && !IsSystemIsolate(isolate)));
  }

  Isolate* target_;
  Isolate::LibMsgId msg_id_;
  bool kill_system_isolates_;
};

void Isolate::KillAllIsolates(LibMsgId msg_id) {
  IsolateKillerVisitor visitor(msg_id);
  VisitIsolates(&visitor);
}

void Isolate::KillAllSystemIsolates(LibMsgId msg_id) {
  IsolateKillerVisitor visitor(msg_id, /*kill_system_isolates=*/true);
  VisitIsolates(&visitor);
}

void Isolate::KillIfExists(Isolate* isolate, LibMsgId msg_id) {
  IsolateKillerVisitor visitor(isolate, msg_id);
  VisitIsolates(&visitor);
}

void Isolate::IncrementSpawnCount() {
  MonitorLocker ml(&spawn_count_monitor_);
  spawn_count_++;
}

void Isolate::DecrementSpawnCount() {
  MonitorLocker ml(&spawn_count_monitor_);
  ASSERT(spawn_count_ > 0);
  spawn_count_--;
  ml.Notify();
}

void Isolate::WaitForOutstandingSpawns() {
  Thread* thread = Thread::Current();
  ASSERT(thread != nullptr);
  MonitorLocker ml(&spawn_count_monitor_);
  while (spawn_count_ > 0) {
    ml.WaitWithSafepointCheck(thread);
  }
}

FfiCallbackMetadata::Trampoline Isolate::CreateAsyncFfiCallback(
    Zone* zone,
    const Function& send_function,
    Dart_Port send_port) {
  return FfiCallbackMetadata::Instance()->CreateAsyncFfiCallback(
      this, zone, send_function, send_port, &ffi_callback_list_head_);
}

FfiCallbackMetadata::Trampoline Isolate::CreateIsolateLocalFfiCallback(
    Zone* zone,
    const Function& trampoline,
    const Closure& target,
    bool keep_isolate_alive) {
  if (keep_isolate_alive) {
    UpdateNativeCallableKeepIsolateAliveCounter(1);
  }
  return FfiCallbackMetadata::Instance()->CreateIsolateLocalFfiCallback(
      this, zone, trampoline, target, &ffi_callback_list_head_);
}

bool Isolate::HasLivePorts() {
  ASSERT(0 <= open_ports_ && 0 <= open_ports_keepalive_ &&
         open_ports_keepalive_ <= open_ports_);
  return open_ports_keepalive_ > 0;
}

ReceivePortPtr Isolate::CreateReceivePort(const String& debug_name) {
  Dart_Port port_id = PortMap::CreatePort(message_handler());
  ++open_ports_;
  ++open_ports_keepalive_;
  return ReceivePort::New(port_id, debug_name);
}

void Isolate::SetReceivePortKeepAliveState(const ReceivePort& receive_port,
                                           bool keep_isolate_alive) {
  // Changing keep-isolate-alive state of a closed port is a NOP.
  if (!receive_port.is_open()) return;

  ASSERT(0 < open_ports_);

  // If the state doesn't change it's a NOP.
  if (receive_port.keep_isolate_alive() == keep_isolate_alive) return;

  if (keep_isolate_alive) {
    ASSERT(open_ports_keepalive_ < open_ports_);
    ++open_ports_keepalive_;
  } else {
    ASSERT(0 < open_ports_keepalive_);
    --open_ports_keepalive_;
  }
  receive_port.set_keep_isolate_alive(keep_isolate_alive);
}

void Isolate::CloseReceivePort(const ReceivePort& receive_port) {
  // Closing an already closed port is a NOP.
  if (!receive_port.is_open()) return;

  ASSERT(open_ports_ > 0);
  const bool ok = PortMap::ClosePort(receive_port.Id());
  RELEASE_ASSERT(ok);

  if (receive_port.keep_isolate_alive()) {
    --open_ports_keepalive_;
    receive_port.set_keep_isolate_alive(false);
  }
  --open_ports_;
  receive_port.set_is_open(false);
}

void Isolate::DeleteFfiCallback(FfiCallbackMetadata::Trampoline callback) {
  FfiCallbackMetadata::Instance()->DeleteCallback(callback,
                                                  &ffi_callback_list_head_);
}

void Isolate::UpdateNativeCallableKeepIsolateAliveCounter(intptr_t delta) {
  ffi_callback_keep_alive_counter_ += delta;
  ASSERT(ffi_callback_keep_alive_counter_ >= 0);
}

bool Isolate::HasOpenNativeCallables() {
  ASSERT(ffi_callback_keep_alive_counter_ >= 0);
  return ffi_callback_keep_alive_counter_ > 0;
}

#if !defined(PRODUCT)
void IsolateGroup::CloneClassTableForReload() {
  RELEASE_ASSERT(class_table_ == heap_walk_class_table_);
  class_table_ = class_table_->Clone();
  set_cached_class_table_table(nullptr);
}

void IsolateGroup::RestoreOriginalClassTable() {
  RELEASE_ASSERT(class_table_ != heap_walk_class_table_);
  class_table_allocator_.Free(class_table_);
  class_table_ = heap_walk_class_table_;
  set_cached_class_table_table(class_table_->table());
}

void IsolateGroup::DropOriginalClassTable() {
  RELEASE_ASSERT(class_table_ != heap_walk_class_table_);
  class_table_allocator_.Free(heap_walk_class_table_);
  heap_walk_class_table_ = class_table_;
  set_cached_class_table_table(class_table_->table());
}
#endif

}  // namespace dart
