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

#include "vm/class_table.h"

#include <limits>
#include <memory>

#include "platform/atomic.h"
#include "vm/flags.h"
#include "vm/growable_array.h"
#include "vm/heap/heap.h"
#include "vm/object.h"
#include "vm/object_graph.h"
#include "vm/raw_object.h"
#include "vm/visitor.h"

namespace dart {

DEFINE_FLAG(bool, print_class_table, false, "Print initial class table.");

SharedClassTable::SharedClassTable()
    : top_(kNumPredefinedCids),
      capacity_(0),
      old_tables_(new MallocGrowableArray<void*>()) {
  if (Dart::vm_isolate() == NULL) {
    ASSERT(kInitialCapacity >= kNumPredefinedCids);
    capacity_ = kInitialCapacity;
    // Note that [calloc] will zero-initialize the memory.
    table_.store(reinterpret_cast<RelaxedAtomic<intptr_t>*>(
        calloc(capacity_, sizeof(RelaxedAtomic<intptr_t>))));
  } else {
    // Duplicate the class table from the VM isolate.
    auto vm_shared_class_table = Dart::vm_isolate_group()->shared_class_table();
    capacity_ = vm_shared_class_table->capacity_;
    // Note that [calloc] will zero-initialize the memory.
    RelaxedAtomic<intptr_t>* table = reinterpret_cast<RelaxedAtomic<intptr_t>*>(
        calloc(capacity_, sizeof(RelaxedAtomic<intptr_t>)));
    // The following cids don't have a corresponding class object in Dart code.
    // We therefore need to initialize them eagerly.
    COMPILE_ASSERT(kFirstInternalOnlyCid == kObjectCid + 1);
    for (intptr_t i = kObjectCid; i <= kLastInternalOnlyCid; i++) {
      table[i] = vm_shared_class_table->SizeAt(i);
    }
    table[kTypeArgumentsCid] = vm_shared_class_table->SizeAt(kTypeArgumentsCid);
    table[kFreeListElement] = vm_shared_class_table->SizeAt(kFreeListElement);
    table[kForwardingCorpse] = vm_shared_class_table->SizeAt(kForwardingCorpse);
    table[kDynamicCid] = vm_shared_class_table->SizeAt(kDynamicCid);
    table[kVoidCid] = vm_shared_class_table->SizeAt(kVoidCid);
    table_.store(table);
  }
#if defined(SUPPORT_UNBOXED_INSTANCE_FIELDS)
  // Note that [calloc] will zero-initialize the memory.
  unboxed_fields_map_ = static_cast<UnboxedFieldBitmap*>(
      calloc(capacity_, sizeof(UnboxedFieldBitmap)));
#endif  // defined(SUPPORT_UNBOXED_INSTANCE_FIELDS)
#ifndef PRODUCT
  // Note that [calloc] will zero-initialize the memory.
  trace_allocation_table_.store(
      static_cast<uint8_t*>(calloc(capacity_, sizeof(uint8_t))));
#endif  // !PRODUCT
}
SharedClassTable::~SharedClassTable() {
  if (old_tables_ != NULL) {
    FreeOldTables();
    delete old_tables_;
  }
  free(table_.load());
  free(unboxed_fields_map_);

  NOT_IN_PRODUCT(free(trace_allocation_table_.load()));
}

void ClassTable::set_table(ClassPtr* table) {
  // We don't have to stop mutators, since the old table is the prefix of the
  // new table. But we should ensure that all writes to the current table are
  // visible once the new table is visible.
  table_.store(table);
  IsolateGroup::Current()->set_cached_class_table_table(table);
}

ClassTable::ClassTable(SharedClassTable* shared_class_table)
    : top_(kNumPredefinedCids),
      capacity_(0),
      tlc_top_(0),
      tlc_capacity_(0),
      table_(nullptr),
      tlc_table_(nullptr),
      old_class_tables_(new MallocGrowableArray<ClassPtr*>()),
      shared_class_table_(shared_class_table) {
  if (Dart::vm_isolate() == NULL) {
    ASSERT(kInitialCapacity >= kNumPredefinedCids);
    capacity_ = kInitialCapacity;
    // Note that [calloc] will zero-initialize the memory.
    // Don't use set_table because caller is supposed to set up isolates
    // cached copy when constructing ClassTable. Isolate::Current might not
    // be available at this point yet.
    table_.store(static_cast<ClassPtr*>(calloc(capacity_, sizeof(ClassPtr))));
  } else {
    // Duplicate the class table from the VM isolate.
    ClassTable* vm_class_table = Dart::vm_isolate_group()->class_table();
    capacity_ = vm_class_table->capacity_;
    // Note that [calloc] will zero-initialize the memory.
    ClassPtr* table =
        static_cast<ClassPtr*>(calloc(capacity_, sizeof(ClassPtr)));
    // The following cids don't have a corresponding class object in Dart code.
    // We therefore need to initialize them eagerly.
    COMPILE_ASSERT(kFirstInternalOnlyCid == kObjectCid + 1);
    for (intptr_t i = kObjectCid; i <= kLastInternalOnlyCid; i++) {
      table[i] = vm_class_table->At(i);
    }
    table[kTypeArgumentsCid] = vm_class_table->At(kTypeArgumentsCid);
    table[kFreeListElement] = vm_class_table->At(kFreeListElement);
    table[kForwardingCorpse] = vm_class_table->At(kForwardingCorpse);
    table[kDynamicCid] = vm_class_table->At(kDynamicCid);
    table[kVoidCid] = vm_class_table->At(kVoidCid);
    // Don't use set_table because caller is supposed to set up isolates
    // cached copy when constructing ClassTable. Isolate::Current might not
    // be available at this point yet.
    table_.store(table);
  }
}

ClassTable::~ClassTable() {
  if (old_class_tables_ != nullptr) {
    FreeOldTables();
    delete old_class_tables_;
  }
  free(table_.load());
  free(tlc_table_.load());
}

void ClassTable::AddOldTable(ClassPtr* old_class_table) {
  ASSERT(Thread::Current()->IsMutatorThread());
  old_class_tables_->Add(old_class_table);
}

void ClassTable::FreeOldTables() {
  while (old_class_tables_->length() > 0) {
    free(old_class_tables_->RemoveLast());
  }
}

void SharedClassTable::AddOldTable(intptr_t* old_table) {
  ASSERT(Thread::Current()->IsMutatorThread());
  old_tables_->Add(old_table);
}

void SharedClassTable::FreeOldTables() {
  while (old_tables_->length() > 0) {
    free(old_tables_->RemoveLast());
  }
}

void ClassTable::Register(const Class& cls) {
  ASSERT(Thread::Current()->IsMutatorThread());

  const classid_t cid = cls.id();
  ASSERT(!IsTopLevelCid(cid));

  // During the transition period we would like [SharedClassTable] to operate in
  // parallel to [ClassTable].

  const intptr_t instance_size =
      cls.is_abstract() ? 0 : Class::host_instance_size(cls.ptr());

  const intptr_t expected_cid =
      shared_class_table_->Register(cid, instance_size);

  if (cid != kIllegalCid) {
    ASSERT(cid > 0 && cid < kNumPredefinedCids && cid < top_);
    ASSERT(table_.load()[cid] == nullptr);
    table_.load()[cid] = cls.ptr();
  } else {
    if (top_ == capacity_) {
      const intptr_t new_capacity = capacity_ + kCapacityIncrement;
      Grow(new_capacity);
    }
    ASSERT(top_ < capacity_);
    cls.set_id(top_);
    table_.load()[top_] = cls.ptr();
    top_++;  // Increment next index.
  }
  ASSERT(expected_cid == cls.id());
}

void ClassTable::RegisterTopLevel(const Class& cls) {
  if (top_ >= std::numeric_limits<classid_t>::max()) {
    FATAL1("Fatal error in ClassTable::RegisterTopLevel: invalid index %" Pd
           "\n",
           top_);
  }

  ASSERT(Thread::Current()->IsMutatorThread());

  const intptr_t index = cls.id();
  ASSERT(index == kIllegalCid);

  if (tlc_top_ == tlc_capacity_) {
    const intptr_t new_capacity = tlc_capacity_ + kCapacityIncrement;
    GrowTopLevel(new_capacity);
  }
  ASSERT(tlc_top_ < tlc_capacity_);
  cls.set_id(ClassTable::CidFromTopLevelIndex(tlc_top_));
  tlc_table_.load()[tlc_top_] = cls.ptr();
  tlc_top_++;  // Increment next index.
}

intptr_t SharedClassTable::Register(intptr_t index, intptr_t size) {
  if (!Class::is_valid_id(top_)) {
    FATAL1("Fatal error in SharedClassTable::Register: invalid index %" Pd "\n",
           top_);
  }

  ASSERT(Thread::Current()->IsMutatorThread());
  if (index != kIllegalCid) {
    // We are registring the size of a predefined class.
    ASSERT(index > 0 && index < kNumPredefinedCids);
    SetSizeAt(index, size);
    return index;
  } else {
    ASSERT(size == 0);
    if (top_ == capacity_) {
      const intptr_t new_capacity = capacity_ + kCapacityIncrement;
      Grow(new_capacity);
    }
    ASSERT(top_ < capacity_);
    table_.load()[top_] = size;
    return top_++;  // Increment next index.
  }
}

void ClassTable::AllocateIndex(intptr_t index) {
  if (IsTopLevelCid(index)) {
    AllocateTopLevelIndex(index);
    return;
  }

  // This is called by a snapshot reader.
  shared_class_table_->AllocateIndex(index);
  ASSERT(Class::is_valid_id(index));

  if (index >= capacity_) {
    const intptr_t new_capacity = index + kCapacityIncrement;
    Grow(new_capacity);
  }

  ASSERT(table_.load()[index] == nullptr);
  if (index >= top_) {
    top_ = index + 1;
  }

  ASSERT(top_ == shared_class_table_->top_);
  ASSERT(capacity_ == shared_class_table_->capacity_);
}

void ClassTable::AllocateTopLevelIndex(intptr_t cid) {
  ASSERT(IsTopLevelCid(cid));
  const intptr_t tlc_index = IndexFromTopLevelCid(cid);

  if (tlc_index >= tlc_capacity_) {
    const intptr_t new_capacity = tlc_index + kCapacityIncrement;
    GrowTopLevel(new_capacity);
  }

  ASSERT(tlc_table_.load()[tlc_index] == nullptr);
  if (tlc_index >= tlc_top_) {
    tlc_top_ = tlc_index + 1;
  }
}

void ClassTable::Grow(intptr_t new_capacity) {
  ASSERT(new_capacity > capacity_);

  auto old_table = table_.load();
  auto new_table = static_cast<ClassPtr*>(
      malloc(new_capacity * sizeof(ClassPtr)));  // NOLINT
  intptr_t i;
  for (i = 0; i < capacity_; i++) {
    // Don't use memmove, which changes this from a relaxed atomic operation
    // to a non-atomic operation.
    new_table[i] = old_table[i];
  }
  for (; i < new_capacity; i++) {
    // Don't use memset, which changes this from a relaxed atomic operation
    // to a non-atomic operation.
    new_table[i] = 0;
  }
  old_class_tables_->Add(old_table);
  set_table(new_table);

  capacity_ = new_capacity;
}

void ClassTable::GrowTopLevel(intptr_t new_capacity) {
  ASSERT(new_capacity > tlc_capacity_);

  auto old_table = tlc_table_.load();
  auto new_table = static_cast<ClassPtr*>(
      malloc(new_capacity * sizeof(ClassPtr)));  // NOLINT
  intptr_t i;
  for (i = 0; i < tlc_capacity_; i++) {
    // Don't use memmove, which changes this from a relaxed atomic operation
    // to a non-atomic operation.
    new_table[i] = old_table[i];
  }
  for (; i < new_capacity; i++) {
    // Don't use memset, which changes this from a relaxed atomic operation
    // to a non-atomic operation.
    new_table[i] = 0;
  }
  old_class_tables_->Add(old_table);

  tlc_table_.store(new_table);
  tlc_capacity_ = new_capacity;
}

void SharedClassTable::AllocateIndex(intptr_t index) {
  // This is called by a snapshot reader.
  ASSERT(Class::is_valid_id(index));

  if (index >= capacity_) {
    const intptr_t new_capacity = index + kCapacityIncrement;
    Grow(new_capacity);
  }

  ASSERT(table_.load()[index] == 0);
  if (index >= top_) {
    top_ = index + 1;
  }
}

void SharedClassTable::Grow(intptr_t new_capacity) {
  ASSERT(new_capacity >= capacity_);

  RelaxedAtomic<intptr_t>* old_table = table_.load();
  RelaxedAtomic<intptr_t>* new_table =
      reinterpret_cast<RelaxedAtomic<intptr_t>*>(
          malloc(new_capacity * sizeof(RelaxedAtomic<intptr_t>)));  // NOLINT

  intptr_t i;
  for (i = 0; i < capacity_; i++) {
    // Don't use memmove, which changes this from a relaxed atomic operation
    // to a non-atomic operation.
    new_table[i] = old_table[i];
  }
  for (; i < new_capacity; i++) {
    // Don't use memset, which changes this from a relaxed atomic operation
    // to a non-atomic operation.
    new_table[i] = 0;
  }

#if !defined(PRODUCT)
  auto old_trace_table = trace_allocation_table_.load();
  auto new_trace_table =
      static_cast<uint8_t*>(malloc(new_capacity * sizeof(uint8_t)));  // NOLINT
  for (i = 0; i < capacity_; i++) {
    // Don't use memmove, which changes this from a relaxed atomic operation
    // to a non-atomic operation.
    new_trace_table[i] = old_trace_table[i];
  }
  for (; i < new_capacity; i++) {
    // Don't use memset, which changes this from a relaxed atomic operation
    // to a non-atomic operation.
    new_trace_table[i] = 0;
  }
#endif

  old_tables_->Add(old_table);
  table_.store(new_table);
  NOT_IN_PRODUCT(old_tables_->Add(old_trace_table));
  NOT_IN_PRODUCT(trace_allocation_table_.store(new_trace_table));

#if defined(SUPPORT_UNBOXED_INSTANCE_FIELDS)
  auto old_unboxed_fields_map = unboxed_fields_map_;
  auto new_unboxed_fields_map = static_cast<UnboxedFieldBitmap*>(
      malloc(new_capacity * sizeof(UnboxedFieldBitmap)));
  for (i = 0; i < capacity_; i++) {
    // Don't use memmove, which changes this from a relaxed atomic operation
    // to a non-atomic operation.
    new_unboxed_fields_map[i] = old_unboxed_fields_map[i];
  }
  for (; i < new_capacity; i++) {
    // Don't use memset, which changes this from a relaxed atomic operation
    // to a non-atomic operation.
    new_unboxed_fields_map[i] = UnboxedFieldBitmap(0);
  }
  old_tables_->Add(old_unboxed_fields_map);
  unboxed_fields_map_ = new_unboxed_fields_map;
#endif  // defined(SUPPORT_UNBOXED_INSTANCE_FIELDS)

  capacity_ = new_capacity;
}

void ClassTable::Unregister(intptr_t cid) {
  ASSERT(!IsTopLevelCid(cid));
  shared_class_table_->Unregister(cid);
  table_.load()[cid] = nullptr;
}

void ClassTable::UnregisterTopLevel(intptr_t cid) {
  ASSERT(IsTopLevelCid(cid));
  const intptr_t tlc_index = IndexFromTopLevelCid(cid);
  tlc_table_.load()[tlc_index] = nullptr;
}

void SharedClassTable::Unregister(intptr_t index) {
  table_.load()[index] = 0;
#if defined(SUPPORT_UNBOXED_INSTANCE_FIELDS)
  unboxed_fields_map_[index].Reset();
#endif  // defined(SUPPORT_UNBOXED_INSTANCE_FIELDS)
}

void ClassTable::Remap(intptr_t* old_to_new_cid) {
  ASSERT(Thread::Current()->IsAtSafepoint(SafepointLevel::kGCAndDeopt));
  const intptr_t num_cids = NumCids();
  std::unique_ptr<ClassPtr[]> cls_by_old_cid(new ClassPtr[num_cids]);
  auto* table = table_.load();
  memmove(cls_by_old_cid.get(), table, sizeof(ClassPtr) * num_cids);
  for (intptr_t i = 0; i < num_cids; i++) {
    table[old_to_new_cid[i]] = cls_by_old_cid[i];
  }
}

void SharedClassTable::Remap(intptr_t* old_to_new_cid) {
  ASSERT(Thread::Current()->IsAtSafepoint(SafepointLevel::kGCAndDeopt));
  const intptr_t num_cids = NumCids();
  std::unique_ptr<intptr_t[]> size_by_old_cid(new intptr_t[num_cids]);
  auto* table = table_.load();
  for (intptr_t i = 0; i < num_cids; i++) {
    size_by_old_cid[i] = table[i];
  }
  for (intptr_t i = 0; i < num_cids; i++) {
    table[old_to_new_cid[i]] = size_by_old_cid[i];
  }

#if defined(SUPPORT_UNBOXED_INSTANCE_FIELDS)
  std::unique_ptr<UnboxedFieldBitmap[]> unboxed_fields_by_old_cid(
      new UnboxedFieldBitmap[num_cids]);
  for (intptr_t i = 0; i < num_cids; i++) {
    unboxed_fields_by_old_cid[i] = unboxed_fields_map_[i];
  }
  for (intptr_t i = 0; i < num_cids; i++) {
    unboxed_fields_map_[old_to_new_cid[i]] = unboxed_fields_by_old_cid[i];
  }
#endif  // defined(SUPPORT_UNBOXED_INSTANCE_FIELDS)
}

void ClassTable::VisitObjectPointers(ObjectPointerVisitor* visitor) {
  ASSERT(visitor != NULL);
  visitor->set_gc_root_type("class table");
  if (top_ != 0) {
    auto* table = table_.load();
    ObjectPtr* from = reinterpret_cast<ObjectPtr*>(&table[0]);
    ObjectPtr* to = reinterpret_cast<ObjectPtr*>(&table[top_ - 1]);
    visitor->VisitPointers(from, to);
  }
  if (tlc_top_ != 0) {
    auto* tlc_table = tlc_table_.load();
    ObjectPtr* from = reinterpret_cast<ObjectPtr*>(&tlc_table[0]);
    ObjectPtr* to = reinterpret_cast<ObjectPtr*>(&tlc_table[tlc_top_ - 1]);
    visitor->VisitPointers(from, to);
  }
  visitor->clear_gc_root_type();
}

void ClassTable::CopySizesFromClassObjects() {
  ASSERT(kIllegalCid == 0);
  for (intptr_t i = 1; i < top_; i++) {
    SetAt(i, At(i));
  }
}

void ClassTable::Validate() {
  Class& cls = Class::Handle();
  for (intptr_t cid = kNumPredefinedCids; cid < top_; cid++) {
    // Some of the class table entries maybe NULL as we create some
    // top level classes but do not add them to the list of anonymous
    // classes in a library if there are no top level fields or functions.
    // Since there are no references to these top level classes they are
    // not written into a full snapshot and will not be recreated when
    // we read back the full snapshot. These class slots end up with NULL
    // entries.
    if (HasValidClassAt(cid)) {
      cls = At(cid);
      ASSERT(cls.IsClass());
#if defined(DART_PRECOMPILER)
      // Precompiler can drop classes and set their id() to kIllegalCid.
      // It still leaves them in the class table so dropped program
      // structure could still be accessed while writing debug info.
      ASSERT((cls.id() == cid) || (cls.id() == kIllegalCid));
#else
      ASSERT(cls.id() == cid);
#endif  // defined(DART_PRECOMPILER)
    }
  }
}

void ClassTable::Print() {
  Class& cls = Class::Handle();
  String& name = String::Handle();

  for (intptr_t i = 1; i < top_; i++) {
    if (!HasValidClassAt(i)) {
      continue;
    }
    cls = At(i);
    if (cls.ptr() != nullptr) {
      name = cls.Name();
      OS::PrintErr("%" Pd ": %s\n", i, name.ToCString());
    }
  }
}

void ClassTable::SetAt(intptr_t cid, ClassPtr raw_cls) {
  if (IsTopLevelCid(cid)) {
    tlc_table_.load()[IndexFromTopLevelCid(cid)] = raw_cls;
    return;
  }

  // This is called by snapshot reader and class finalizer.
  ASSERT(cid < capacity_);
  UpdateClassSize(cid, raw_cls);
  table_.load()[cid] = raw_cls;
}

void ClassTable::UpdateClassSize(intptr_t cid, ClassPtr raw_cls) {
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  ASSERT(!IsTopLevelCid(cid));  // "top-level" classes don't get instantiated
  ASSERT(cid < capacity_);
  const intptr_t size =
      raw_cls == nullptr ? 0 : Class::host_instance_size(raw_cls);
  shared_class_table_->SetSizeAt(cid, size);
}

#if defined(DART_PRECOMPILER)
void ClassTable::PrintObjectLayout(const char* filename) {
  Class& cls = Class::Handle();
  Array& fields = Array::Handle();
  Field& field = Field::Handle();

  JSONWriter js;
  js.OpenArray();
  for (intptr_t i = ClassId::kObjectCid; i < top_; i++) {
    if (!HasValidClassAt(i)) {
      continue;
    }
    cls = At(i);
    ASSERT(!cls.IsNull());
    ASSERT(cls.id() != kIllegalCid);
    ASSERT(cls.is_finalized());  // Precompiler already finalized all classes.
    ASSERT(!cls.IsTopLevel());
    js.OpenObject();
    js.PrintProperty("class", cls.UserVisibleNameCString());
    js.PrintProperty("size", cls.target_instance_size());
    js.OpenArray("fields");
    fields = cls.fields();
    if (!fields.IsNull()) {
      for (intptr_t i = 0, n = fields.Length(); i < n; ++i) {
        field ^= fields.At(i);
        js.OpenObject();
        js.PrintProperty("field", field.UserVisibleNameCString());
        if (field.is_static()) {
          js.PrintPropertyBool("static", true);
        } else {
          js.PrintProperty("offset", field.TargetOffset());
        }
        js.CloseObject();
      }
    }
    js.CloseArray();
    js.CloseObject();
  }
  js.CloseArray();

  auto file_open = Dart::file_open_callback();
  auto file_write = Dart::file_write_callback();
  auto file_close = Dart::file_close_callback();
  if ((file_open == nullptr) || (file_write == nullptr) ||
      (file_close == nullptr)) {
    OS::PrintErr("warning: Could not access file callbacks.");
    return;
  }

  void* file = file_open(filename, /*write=*/true);
  if (file == nullptr) {
    OS::PrintErr("warning: Failed to write object layout: %s\n", filename);
    return;
  }

  char* output = nullptr;
  intptr_t output_length = 0;
  js.Steal(&output, &output_length);
  file_write(output, output_length, file);
  free(output);
  file_close(file);
}
#endif  // defined(DART_PRECOMPILER)

#ifndef PRODUCT
void ClassTable::PrintToJSONObject(JSONObject* object) {
  Class& cls = Class::Handle();
  object->AddProperty("type", "ClassList");
  {
    JSONArray members(object, "classes");
    for (intptr_t i = ClassId::kObjectCid; i < top_; i++) {
      if (HasValidClassAt(i)) {
        cls = At(i);
        members.AddValue(cls);
      }
    }
  }
}

intptr_t SharedClassTable::ClassOffsetFor(intptr_t cid) {
  return cid * sizeof(uint8_t);  // NOLINT
}


void ClassTable::AllocationProfilePrintJSON(JSONStream* stream, bool internal) {
  Isolate* isolate = Isolate::Current();
  ASSERT(isolate != NULL);
  auto isolate_group = isolate->group();
  Heap* heap = isolate_group->heap();
  ASSERT(heap != NULL);
  JSONObject obj(stream);
  obj.AddProperty("type", "AllocationProfile");
  if (isolate_group->last_allocationprofile_accumulator_reset_timestamp() !=
      0) {
    obj.AddPropertyF(
        "dateLastAccumulatorReset", "%" Pd64 "",
        isolate_group->last_allocationprofile_accumulator_reset_timestamp());
  }
  if (isolate_group->last_allocationprofile_gc_timestamp() != 0) {
    obj.AddPropertyF("dateLastServiceGC", "%" Pd64 "",
                     isolate_group->last_allocationprofile_gc_timestamp());
  }

  if (internal) {
    JSONObject heaps(&obj, "_heaps");
    { heap->PrintToJSONObject(Heap::kNew, &heaps); }
    { heap->PrintToJSONObject(Heap::kOld, &heaps); }
  }

  {
    JSONObject memory(&obj, "memoryUsage");
    { heap->PrintMemoryUsageJSON(&memory); }
  }

  Thread* thread = Thread::Current();
  CountObjectsVisitor visitor(thread, NumCids());
  {
    HeapIterationScope iter(thread);
    iter.IterateObjects(&visitor);
    isolate->group()->VisitWeakPersistentHandles(&visitor);
  }

  {
    JSONArray arr(&obj, "members");
    Class& cls = Class::Handle();
    for (intptr_t i = 3; i < top_; i++) {
      if (!HasValidClassAt(i)) continue;

      cls = At(i);
      if (cls.IsNull()) continue;

      JSONObject obj(&arr);
      obj.AddProperty("type", "ClassHeapStats");
      obj.AddProperty("class", cls);
      intptr_t count = visitor.new_count_[i] + visitor.old_count_[i];
      intptr_t size = visitor.new_size_[i] + visitor.old_size_[i];
      obj.AddProperty64("instancesAccumulated", count);
      obj.AddProperty64("accumulatedSize", size);
      obj.AddProperty64("instancesCurrent", count);
      obj.AddProperty64("bytesCurrent", size);

      if (internal) {
        {
          JSONArray new_stats(&obj, "_new");
          new_stats.AddValue(visitor.new_count_[i]);
          new_stats.AddValue(visitor.new_size_[i]);
          new_stats.AddValue(visitor.new_external_size_[i]);
        }
        {
          JSONArray old_stats(&obj, "_old");
          old_stats.AddValue(visitor.old_count_[i]);
          old_stats.AddValue(visitor.old_size_[i]);
          old_stats.AddValue(visitor.old_external_size_[i]);
        }
      }
    }
  }
}
#endif  // !PRODUCT

}  // namespace dart
