// 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 "platform/atomic.h"
#include "vm/flags.h"
#include "vm/growable_array.h"
#include "vm/heap/heap.h"
#include "vm/object.h"
#include "vm/raw_object.h"
#include "vm/visitor.h"

namespace dart {

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

ClassTable::ClassTable()
    : top_(kNumPredefinedCids),
      capacity_(0),
      table_(NULL),
      old_tables_(new MallocGrowableArray<ClassAndSize*>()) {
  NOT_IN_PRODUCT(class_heap_stats_table_ = NULL);
  if (Dart::vm_isolate() == NULL) {
    capacity_ = initial_capacity_;
    table_ = reinterpret_cast<ClassAndSize*>(
        calloc(capacity_, sizeof(ClassAndSize)));  // NOLINT
  } else {
    // Duplicate the class table from the VM isolate.
    ClassTable* vm_class_table = Dart::vm_isolate()->class_table();
    capacity_ = vm_class_table->capacity_;
    table_ = reinterpret_cast<ClassAndSize*>(
        calloc(capacity_, sizeof(ClassAndSize)));  // NOLINT
    for (intptr_t i = kObjectCid; i < kInstanceCid; i++) {
      table_[i] = vm_class_table->PairAt(i);
    }
    table_[kTypeArgumentsCid] = vm_class_table->PairAt(kTypeArgumentsCid);
    table_[kFreeListElement] = vm_class_table->PairAt(kFreeListElement);
    table_[kForwardingCorpse] = vm_class_table->PairAt(kForwardingCorpse);
    table_[kDynamicCid] = vm_class_table->PairAt(kDynamicCid);
    table_[kVoidCid] = vm_class_table->PairAt(kVoidCid);
  }
#ifndef PRODUCT
  class_heap_stats_table_ = reinterpret_cast<ClassHeapStats*>(
      calloc(capacity_, sizeof(ClassHeapStats)));  // NOLINT
  for (intptr_t i = 0; i < capacity_; i++) {
    class_heap_stats_table_[i].Initialize();
  }
#endif  // !PRODUCT
}

ClassTable::ClassTable(ClassTable* original)
    : top_(original->top_),
      capacity_(original->top_),
      table_(original->table_),
      old_tables_(NULL) {
  NOT_IN_PRODUCT(class_heap_stats_table_ = NULL);
}

ClassTable::~ClassTable() {
  if (old_tables_ != NULL) {
    FreeOldTables();
    delete old_tables_;
    free(table_);
    NOT_IN_PRODUCT(free(class_heap_stats_table_));
  } else {
    // This instance was a shallow copy. It doesn't own any memory.
    NOT_IN_PRODUCT(ASSERT(class_heap_stats_table_ == NULL));
  }
}

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

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

void ClassTable::Register(const Class& cls) {
  ASSERT(Thread::Current()->IsMutatorThread());
  intptr_t index = cls.id();
  if (index != kIllegalCid) {
    ASSERT(index > 0);
    ASSERT(index < kNumPredefinedCids);
    ASSERT(table_[index].class_ == NULL);
    ASSERT(index < capacity_);
    table_[index] = ClassAndSize(cls.raw(), Class::instance_size(cls.raw()));
    // Add the vtable for this predefined class into the static vtable registry
    // if it has not been setup yet.
    cpp_vtable cls_vtable = cls.handle_vtable();
    cpp_vtable old_cls_vtable = AtomicOperations::CompareAndSwapWord(
        &(Object::builtin_vtables_[index]), 0, cls_vtable);
    if (old_cls_vtable != 0) {
      ASSERT(old_cls_vtable == cls_vtable);
    }
  } else {
    if (top_ == capacity_) {
      // Grow the capacity of the class table.
      // TODO(koda): Add ClassTable::Grow to share code.

#ifndef PRODUCT
      // Wait for any marking tasks to complete. Allocation stats in the
      // marker rely on the class table size not changing.
      Thread* thread = Thread::Current();
      thread->heap()->WaitForMarkerTasks(thread);
#endif

      intptr_t new_capacity = capacity_ + capacity_increment_;
      ClassAndSize* new_table = reinterpret_cast<ClassAndSize*>(
          malloc(new_capacity * sizeof(ClassAndSize)));  // NOLINT
      memmove(new_table, table_, capacity_ * sizeof(ClassAndSize));
#ifndef PRODUCT
      ClassHeapStats* new_stats_table = reinterpret_cast<ClassHeapStats*>(
          realloc(class_heap_stats_table_,
                  new_capacity * sizeof(ClassHeapStats)));  // NOLINT
#endif
      for (intptr_t i = capacity_; i < new_capacity; i++) {
        new_table[i] = ClassAndSize(NULL, 0);
        NOT_IN_PRODUCT(new_stats_table[i].Initialize());
      }
      capacity_ = new_capacity;
      old_tables_->Add(table_);
      table_ = new_table;  // TODO(koda): This should use atomics.
      NOT_IN_PRODUCT(class_heap_stats_table_ = new_stats_table);
    }
    ASSERT(top_ < capacity_);
    if (!Class::is_valid_id(top_)) {
      FATAL1("Fatal error in ClassTable::Register: invalid index %" Pd "\n",
             top_);
    }
    cls.set_id(top_);
    table_[top_] = ClassAndSize(cls.raw());
    top_++;  // Increment next index.
  }
}

void ClassTable::AllocateIndex(intptr_t index) {
  if (index >= capacity_) {
    // Grow the capacity of the class table.
    // TODO(koda): Add ClassTable::Grow to share code.

#ifndef PRODUCT
    // Wait for any marking tasks to complete. Allocation stats in the
    // marker rely on the class table size not changing.
    Thread* thread = Thread::Current();
    thread->heap()->WaitForMarkerTasks(thread);
#endif

    intptr_t new_capacity = index + capacity_increment_;
    if (!Class::is_valid_id(index) || new_capacity < capacity_) {
      FATAL1("Fatal error in ClassTable::Register: invalid index %" Pd "\n",
             index);
    }
    ClassAndSize* new_table = reinterpret_cast<ClassAndSize*>(
        malloc(new_capacity * sizeof(ClassAndSize)));  // NOLINT
    memmove(new_table, table_, capacity_ * sizeof(ClassAndSize));
#ifndef PRODUCT
    ClassHeapStats* new_stats_table = reinterpret_cast<ClassHeapStats*>(
        realloc(class_heap_stats_table_,
                new_capacity * sizeof(ClassHeapStats)));  // NOLINT
#endif
    for (intptr_t i = capacity_; i < new_capacity; i++) {
      new_table[i] = ClassAndSize(NULL);
      NOT_IN_PRODUCT(new_stats_table[i].Initialize());
    }
    capacity_ = new_capacity;
    old_tables_->Add(table_);
    table_ = new_table;  // TODO(koda): This should use atomics.
    NOT_IN_PRODUCT(class_heap_stats_table_ = new_stats_table);
    ASSERT(capacity_increment_ >= 1);
  }

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

void ClassTable::Unregister(intptr_t index) {
  table_[index] = ClassAndSize(NULL);
}

void ClassTable::Remap(intptr_t* old_to_new_cid) {
  ASSERT(Thread::Current()->IsAtSafepoint());
  intptr_t num_cids = NumCids();
  ClassAndSize* cls_by_old_cid = new ClassAndSize[num_cids];
  for (intptr_t i = 0; i < num_cids; i++) {
    cls_by_old_cid[i] = table_[i];
  }
  for (intptr_t i = 0; i < num_cids; i++) {
    table_[old_to_new_cid[i]] = cls_by_old_cid[i];
  }
  delete[] cls_by_old_cid;
}

void ClassTable::VisitObjectPointers(ObjectPointerVisitor* visitor) {
  ASSERT(visitor != NULL);
  for (intptr_t i = 0; i < top_; i++) {
    visitor->VisitPointer(reinterpret_cast<RawObject**>(&(table_[i].class_)));
  }
}

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());
      ASSERT(cls.id() == cid);
    }
  }
}

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.raw() != reinterpret_cast<RawClass*>(0)) {
      name = cls.Name();
      OS::PrintErr("%" Pd ": %s\n", i, name.ToCString());
    }
  }
}

void ClassTable::SetAt(intptr_t index, RawClass* raw_cls) {
  ASSERT(index < capacity_);
  if (raw_cls == NULL) {
    table_[index] = ClassAndSize(raw_cls, 0);
  } else {
    table_[index] = ClassAndSize(raw_cls, Class::instance_size(raw_cls));
  }
}

ClassAndSize::ClassAndSize(RawClass* clazz) : class_(clazz) {
  size_ = clazz == NULL ? 0 : Class::instance_size(clazz);
}

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

void ClassHeapStats::Initialize() {
  pre_gc.Reset();
  post_gc.Reset();
  recent.Reset();
  accumulated.Reset();
  last_reset.Reset();
  promoted_count = 0;
  promoted_size = 0;
  state_ = 0;
  USE(align_);
}

void ClassHeapStats::ResetAtNewGC() {
  Verify();
  pre_gc.new_count = post_gc.new_count + recent.new_count;
  pre_gc.new_size = post_gc.new_size + recent.new_size;
  pre_gc.new_external_size =
      post_gc.new_external_size + recent.new_external_size;
  pre_gc.old_external_size =
      post_gc.old_external_size + recent.old_external_size;
  // Accumulate allocations.
  accumulated.new_count += recent.new_count - last_reset.new_count;
  accumulated.new_size += recent.new_size - last_reset.new_size;
  accumulated.new_external_size +=
      recent.new_external_size - last_reset.new_external_size;
  accumulated.old_external_size +=
      recent.old_external_size - last_reset.old_external_size;
  last_reset.ResetNew();
  post_gc.ResetNew();
  recent.ResetNew();
  old_pre_new_gc_count_ = recent.old_count;
  old_pre_new_gc_size_ = recent.old_size;
}

void ClassHeapStats::ResetAtOldGC() {
  Verify();
  pre_gc.old_count = post_gc.old_count + recent.old_count;
  pre_gc.old_size = post_gc.old_size + recent.old_size;
  pre_gc.old_external_size =
      post_gc.old_external_size + recent.old_external_size;
  pre_gc.new_external_size =
      post_gc.new_external_size + recent.new_external_size;
  // Accumulate allocations.
  accumulated.old_count += recent.old_count - last_reset.old_count;
  accumulated.old_size += recent.old_size - last_reset.old_size;
  accumulated.old_external_size +=
      recent.old_external_size - last_reset.old_external_size;
  accumulated.new_external_size +=
      recent.new_external_size - last_reset.new_external_size;
  last_reset.ResetOld();
  post_gc.ResetOld();
  recent.ResetOld();
}

void ClassHeapStats::Verify() {
  pre_gc.Verify();
  post_gc.Verify();
  recent.Verify();
  accumulated.Verify();
  last_reset.Verify();
}

void ClassHeapStats::UpdateSize(intptr_t instance_size) {
  pre_gc.UpdateSize(instance_size);
  post_gc.UpdateSize(instance_size);
  recent.UpdateSize(instance_size);
  accumulated.UpdateSize(instance_size);
  last_reset.UpdateSize(instance_size);
  promoted_size = promoted_count * instance_size;
  old_pre_new_gc_size_ = old_pre_new_gc_count_ * instance_size;
}

void ClassHeapStats::ResetAccumulator() {
  // Remember how much was allocated so we can subtract this from the result
  // when printing.
  last_reset.new_count = recent.new_count;
  last_reset.new_size = recent.new_size;
  last_reset.new_external_size = recent.new_external_size;
  last_reset.old_count = recent.old_count;
  last_reset.old_size = recent.old_size;
  last_reset.old_external_size = recent.old_external_size;
  accumulated.Reset();
}

void ClassHeapStats::UpdatePromotedAfterNewGC() {
  promoted_count = recent.old_count - old_pre_new_gc_count_;
  promoted_size = recent.old_size - old_pre_new_gc_size_;
}

void ClassHeapStats::PrintToJSONObject(const Class& cls,
                                       JSONObject* obj,
                                       bool internal) const {
  if (!FLAG_support_service) {
    return;
  }
  obj->AddProperty("type", "ClassHeapStats");
  obj->AddProperty("class", cls);
  int64_t accumulated_new =
      accumulated.new_count + recent.new_count - last_reset.new_count;
  int64_t accumulated_old =
      accumulated.old_count + recent.old_count - last_reset.old_count;
  int64_t accumulated_new_size =
      accumulated.new_size + accumulated.new_external_size + recent.new_size +
      recent.new_external_size - last_reset.new_size -
      last_reset.new_external_size;
  int64_t accumulated_old_size =
      accumulated.old_size + accumulated.old_external_size + recent.old_size +
      recent.old_external_size - last_reset.old_size -
      last_reset.old_external_size;
  int64_t instances_new = post_gc.new_count + recent.new_count;
  int64_t instances_old = post_gc.old_count + recent.old_count;
  int64_t live_after_gc_size_new = post_gc.new_size + post_gc.new_external_size;
  int64_t live_after_gc_size_old = post_gc.old_size + post_gc.old_external_size;
  int64_t allocated_since_gc_size_new =
      recent.new_size + recent.new_external_size;
  int64_t allocated_since_gc_size_old =
      recent.old_size + recent.old_external_size;
  int64_t bytes_current = live_after_gc_size_new + live_after_gc_size_old +
                          allocated_since_gc_size_new +
                          allocated_since_gc_size_old;
  if (internal) {
    {
      JSONArray new_stats(obj, "_new");
      new_stats.AddValue(pre_gc.new_count);
      new_stats.AddValue(pre_gc.new_size + pre_gc.new_external_size);
      new_stats.AddValue(post_gc.new_count);
      new_stats.AddValue64(live_after_gc_size_new);
      new_stats.AddValue(recent.new_count);
      new_stats.AddValue64(allocated_since_gc_size_new);
      new_stats.AddValue64(accumulated_new);
      new_stats.AddValue64(accumulated_new_size);
    }
    {
      JSONArray old_stats(obj, "_old");
      old_stats.AddValue(pre_gc.old_count);
      old_stats.AddValue(pre_gc.old_size + pre_gc.old_external_size);
      old_stats.AddValue(post_gc.old_count);
      old_stats.AddValue64(live_after_gc_size_old);
      old_stats.AddValue(recent.old_count);
      old_stats.AddValue64(allocated_since_gc_size_old);
      old_stats.AddValue64(accumulated_old);
      old_stats.AddValue64(accumulated_old_size);
    }
    obj->AddProperty("_promotedInstances", promoted_count);
    obj->AddProperty("_promotedBytes", promoted_size);
  }
  obj->AddProperty64("instancesAccumulated", accumulated_new + accumulated_old);
  obj->AddProperty64("accumulatedSize",
                     accumulated_new_size + accumulated_old_size);
  obj->AddProperty64("instancesCurrent", instances_new + instances_old);
  obj->AddProperty64("bytesCurrent", bytes_current);
}

void ClassTable::UpdateAllocatedOldGC(intptr_t cid, intptr_t size) {
  ClassHeapStats* stats = PreliminaryStatsAt(cid);
  ASSERT(stats != NULL);
  ASSERT(size != 0);
  stats->recent.AddOldGC(size);
}

void ClassTable::UpdateAllocatedExternalNew(intptr_t cid, intptr_t size) {
  ClassHeapStats* stats = PreliminaryStatsAt(cid);
  ASSERT(stats != NULL);
  stats->recent.AddNewExternal(size);
}

void ClassTable::UpdateAllocatedExternalOld(intptr_t cid, intptr_t size) {
  ClassHeapStats* stats = PreliminaryStatsAt(cid);
  ASSERT(stats != NULL);
  stats->recent.AddOldExternal(size);
}

bool ClassTable::ShouldUpdateSizeForClassId(intptr_t cid) {
  return !RawObject::IsVariableSizeClassId(cid);
}

ClassHeapStats* ClassTable::StatsWithUpdatedSize(intptr_t cid) {
  if (!HasValidClassAt(cid) || (cid == kFreeListElement) ||
      (cid == kForwardingCorpse) || (cid == kSmiCid)) {
    return NULL;
  }
  Class& cls = Class::Handle(At(cid));
  if (!(cls.is_finalized() || cls.is_prefinalized())) {
    // Not finalized.
    return NULL;
  }
  ClassHeapStats* stats = PreliminaryStatsAt(cid);
  if (ShouldUpdateSizeForClassId(cid)) {
    stats->UpdateSize(cls.instance_size());
  }
  stats->Verify();
  return stats;
}

void ClassTable::ResetCountersOld() {
  for (intptr_t i = 0; i < top_; i++) {
    class_heap_stats_table_[i].ResetAtOldGC();
  }
}

void ClassTable::ResetCountersNew() {
  for (intptr_t i = 0; i < top_; i++) {
    class_heap_stats_table_[i].ResetAtNewGC();
  }
}

void ClassTable::UpdatePromoted() {
  for (intptr_t i = 0; i < top_; i++) {
    class_heap_stats_table_[i].UpdatePromotedAfterNewGC();
  }
}

intptr_t ClassTable::ClassOffsetFor(intptr_t cid) {
  return cid * sizeof(ClassHeapStats);  // NOLINT
}

intptr_t ClassTable::NewSpaceCounterOffsetFor(intptr_t cid) {
  const intptr_t class_offset = ClassOffsetFor(cid);
  const intptr_t count_field_offset =
      ClassHeapStats::allocated_since_gc_new_space_offset();
  return class_offset + count_field_offset;
}

intptr_t ClassTable::StateOffsetFor(intptr_t cid) {
  return ClassOffsetFor(cid) + ClassHeapStats::state_offset();
}

intptr_t ClassTable::NewSpaceSizeOffsetFor(intptr_t cid) {
  const uword class_offset = ClassOffsetFor(cid);
  const uword size_field_offset =
      ClassHeapStats::allocated_size_since_gc_new_space_offset();
  return class_offset + size_field_offset;
}

void ClassTable::AllocationProfilePrintJSON(JSONStream* stream, bool internal) {
  if (!FLAG_support_service) {
    return;
  }
  Isolate* isolate = Isolate::Current();
  ASSERT(isolate != NULL);
  Heap* heap = isolate->heap();
  ASSERT(heap != NULL);
  JSONObject obj(stream);
  obj.AddProperty("type", "AllocationProfile");
  if (isolate->last_allocationprofile_accumulator_reset_timestamp() != 0) {
    obj.AddPropertyF(
        "dateLastAccumulatorReset", "%" Pd64 "",
        isolate->last_allocationprofile_accumulator_reset_timestamp());
  }
  if (isolate->last_allocationprofile_gc_timestamp() != 0) {
    obj.AddPropertyF("dateLastServiceGC", "%" Pd64 "",
                     isolate->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); }
  }

  {
    JSONArray arr(&obj, "members");
    Class& cls = Class::Handle();
    for (intptr_t i = 1; i < top_; i++) {
      const ClassHeapStats* stats = StatsWithUpdatedSize(i);
      if (stats != NULL) {
        JSONObject obj(&arr);
        cls = At(i);
        stats->PrintToJSONObject(cls, &obj, internal);
      }
    }
  }
}

void ClassTable::ResetAllocationAccumulators() {
  for (intptr_t i = 1; i < top_; i++) {
    ClassHeapStats* stats = StatsWithUpdatedSize(i);
    if (stats != NULL) {
      stats->ResetAccumulator();
    }
  }
}

void ClassTable::UpdateLiveOld(intptr_t cid, intptr_t size, intptr_t count) {
  ClassHeapStats* stats = PreliminaryStatsAt(cid);
  ASSERT(stats != NULL);
  ASSERT(size >= 0);
  ASSERT(count >= 0);
  stats->post_gc.AddOld(size, count);
}

void ClassTable::UpdateLiveNew(intptr_t cid, intptr_t size) {
  ClassHeapStats* stats = PreliminaryStatsAt(cid);
  ASSERT(stats != NULL);
  ASSERT(size >= 0);
  stats->post_gc.AddNew(size);
}

void ClassTable::UpdateLiveNewGC(intptr_t cid, intptr_t size) {
  ClassHeapStats* stats = PreliminaryStatsAt(cid);
  ASSERT(stats != NULL);
  ASSERT(size >= 0);
  stats->post_gc.AddNewGC(size);
}

void ClassTable::UpdateLiveOldExternal(intptr_t cid, intptr_t size) {
  ClassHeapStats* stats = PreliminaryStatsAt(cid);
  ASSERT(stats != NULL);
  ASSERT(size >= 0);
  stats->post_gc.AddOldExternal(size);
}

void ClassTable::UpdateLiveNewExternal(intptr_t cid, intptr_t size) {
  ClassHeapStats* stats = PreliminaryStatsAt(cid);
  ASSERT(stats != NULL);
  ASSERT(size >= 0);
  stats->post_gc.AddNewExternal(size);
}
#endif  // !PRODUCT

}  // namespace dart
