// 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 <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.");

ClassTable::ClassTable(ClassTableAllocator* allocator)
    : allocator_(allocator),
      classes_(allocator),
      top_level_classes_(allocator) {
  if (Dart::vm_isolate() == nullptr) {
    classes_.SetNumCidsAndCapacity(kNumPredefinedCids, kInitialCapacity);
  } else {
    // Duplicate the class table from the VM isolate.
    ClassTable* vm_class_table = Dart::vm_isolate_group()->class_table();
    classes_.SetNumCidsAndCapacity(kNumPredefinedCids,
                                   vm_class_table->classes_.capacity());

    const auto copy_info_for_cid = [&](intptr_t cid) {
      classes_.At<kClassIndex>(cid) = vm_class_table->At(cid);
      classes_.At<kSizeIndex>(cid) = vm_class_table->SizeAt(cid);
    };

    // 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++) {
      copy_info_for_cid(i);
    }
    copy_info_for_cid(kTypeArgumentsCid);
    copy_info_for_cid(kFreeListElement);
    copy_info_for_cid(kForwardingCorpse);
    copy_info_for_cid(kDynamicCid);
    copy_info_for_cid(kVoidCid);
  }
  UpdateCachedAllocationTracingStateTablePointer();
}

ClassTable::~ClassTable() {
#if !defined(PRODUCT) || defined(FORCE_INCLUDE_SAMPLING_HEAP_PROFILER)
  for (intptr_t i = 1; i < classes_.num_cids(); i++) {
    const char* name = UserVisibleNameFor(i);
    if (name != nullptr) {
      free(const_cast<char*>(name));
    }
  }
#endif  // !defined(PRODUCT) || defined(FORCE_INCLUDE_SAMPLING_HEAP_PROFILER)
}

void ClassTable::Register(const Class& cls) {
  ASSERT(Thread::Current()->IsDartMutatorThread());
  ASSERT(cls.id() == kIllegalCid || cls.id() < kNumPredefinedCids);
  bool did_grow = false;
  const classid_t cid =
      cls.id() != kIllegalCid ? cls.id() : classes_.AddRow(&did_grow);
  ASSERT(!IsTopLevelCid(cid));

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

  cls.set_id(cid);
  classes_.At<kClassIndex>(cid) = cls.ptr();
  classes_.At<kSizeIndex>(cid) = static_cast<int32_t>(instance_size);
#if !defined(PRODUCT) || defined(FORCE_INCLUDE_SAMPLING_HEAP_PROFILER)
  classes_.At<kClassNameIndex>(cid) = nullptr;
#endif  // !defined(PRODUCT) || defined(FORCE_INCLUDE_SAMPLING_HEAP_PROFILER)

  if (did_grow) {
    IsolateGroup::Current()->set_cached_class_table_table(
        classes_.GetColumn<kClassIndex>());
    UpdateCachedAllocationTracingStateTablePointer();
  } else {
    // GCC warns that TSAN doesn't understand thread fences.
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic ignored "-Wtsan"
#endif
    std::atomic_thread_fence(std::memory_order_release);
  }
}

void ClassTable::RegisterTopLevel(const Class& cls) {
  ASSERT(Thread::Current()->IsDartMutatorThread());
  ASSERT(cls.id() == kIllegalCid);

  bool did_grow = false;
  const intptr_t index = top_level_classes_.AddRow(&did_grow);
  cls.set_id(ClassTable::CidFromTopLevelIndex(index));
  top_level_classes_.At<kClassIndex>(index) = cls.ptr();
}

void ClassTable::AllocateIndex(intptr_t index) {
  bool did_grow = false;
  if (IsTopLevelCid(index)) {
    top_level_classes_.AllocateIndex(IndexFromTopLevelCid(index), &did_grow);
    return;
  }

  classes_.AllocateIndex(index, &did_grow);
  if (did_grow) {
    IsolateGroup::Current()->set_cached_class_table_table(table());
    UpdateCachedAllocationTracingStateTablePointer();
  }
}

void ClassTable::UnregisterTopLevel(intptr_t cid) {
  ASSERT(IsTopLevelCid(cid));
  const intptr_t tlc_index = IndexFromTopLevelCid(cid);
  top_level_classes_.At<kClassIndex>(tlc_index) = nullptr;
}

void ClassTable::Remap(intptr_t* old_to_new_cid) {
  ASSERT(Thread::Current()->OwnsSafepoint());
  classes_.Remap(old_to_new_cid);
}

void ClassTable::VisitObjectPointers(ObjectPointerVisitor* visitor) {
  ASSERT(visitor != nullptr);
  visitor->set_gc_root_type("class table");

  const auto visit = [&](ClassPtr* table, intptr_t num_cids) {
    if (num_cids == 0) {
      return;
    }
    ObjectPtr* from = reinterpret_cast<ObjectPtr*>(&table[0]);
    ObjectPtr* to = reinterpret_cast<ObjectPtr*>(&table[num_cids - 1]);
    visitor->VisitPointers(from, to);
  };

  visit(classes_.GetColumn<kClassIndex>(), classes_.num_cids());
  visit(top_level_classes_.GetColumn<kClassIndex>(),
        top_level_classes_.num_cids());
  visitor->clear_gc_root_type();
}

void ClassTable::CopySizesFromClassObjects() {
  ASSERT(kIllegalCid == 0);
  for (intptr_t i = 1; i < classes_.num_cids(); i++) {
    UpdateClassSize(i, classes_.At<kClassIndex>(i));
  }
}

void ClassTable::SetAt(intptr_t cid, ClassPtr raw_cls) {
  if (IsTopLevelCid(cid)) {
    top_level_classes_.At<kClassIndex>(IndexFromTopLevelCid(cid)) = raw_cls;
    return;
  }

  // This is called by snapshot reader and class finalizer.
  UpdateClassSize(cid, raw_cls);
  classes_.At<kClassIndex>(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
  const intptr_t size =
      raw_cls == nullptr ? 0 : Class::host_instance_size(raw_cls);
  classes_.At<kSizeIndex>(cid) = static_cast<int32_t>(size);
}

void ClassTable::Validate() {
  Class& cls = Class::Handle();
  for (intptr_t cid = kNumPredefinedCids; cid < classes_.num_cids(); cid++) {
    // Some of the class table entries maybe nullptr 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 nullptr
    // 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 < classes_.num_cids(); i++) {
    if (!HasValidClassAt(i)) {
      continue;
    }
    cls = At(i);
    if (cls.ptr() != nullptr) {
      name = cls.Name();
      OS::PrintErr("%" Pd ": %s\n", i, name.ToCString());
    }
  }
}

#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 < classes_.num_cids(); 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)

#if !defined(PRODUCT) || defined(FORCE_INCLUDE_SAMPLING_HEAP_PROFILER)
void ClassTable::PopulateUserVisibleNames() {
  Class& cls = Class::Handle();
  for (intptr_t i = 0; i < classes_.num_cids(); ++i) {
    if (HasValidClassAt(i) && UserVisibleNameFor(i) == nullptr) {
      cls = At(i);
      cls.SetUserVisibleNameInClassTable();
    }
  }
}
#endif  // !defined(PRODUCT) || defined(FORCE_INCLUDE_SAMPLING_HEAP_PROFILER)

#if !defined(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 < classes_.num_cids(); i++) {
      if (HasValidClassAt(i)) {
        cls = At(i);
        members.AddValue(cls);
      }
    }
  }
}

void ClassTable::AllocationProfilePrintJSON(JSONStream* stream, bool internal) {
  Isolate* isolate = Isolate::Current();
  ASSERT(isolate != nullptr);
  auto isolate_group = isolate->group();
  Heap* heap = isolate_group->heap();
  ASSERT(heap != nullptr);
  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 < classes_.num_cids(); 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

ClassTableAllocator::ClassTableAllocator()
    : pending_freed_(new MallocGrowableArray<std::pair<void*, Deleter>>()) {}

ClassTableAllocator::~ClassTableAllocator() {
  FreePending();
  delete pending_freed_;
}

void ClassTableAllocator::Free(ClassTable* ptr) {
  if (ptr != nullptr) {
    pending_freed_->Add(std::make_pair(
        ptr, [](void* ptr) { delete static_cast<ClassTable*>(ptr); }));
  }
}

void ClassTableAllocator::Free(void* ptr) {
  if (ptr != nullptr) {
    pending_freed_->Add(std::make_pair(ptr, nullptr));
  }
}

void ClassTableAllocator::FreePending() {
  while (!pending_freed_->is_empty()) {
    auto [ptr, deleter] = pending_freed_->RemoveLast();
    if (deleter == nullptr) {
      free(ptr);
    } else {
      deleter(ptr);
    }
  }
}

}  // namespace dart
