// 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 "vm/flags.h"
#include "vm/freelist.h"
#include "vm/heap_trace.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) {
  if (Dart::vm_isolate() == NULL) {
    capacity_ = initial_capacity_;
    table_ = reinterpret_cast<RawClass**>(
        calloc(capacity_, sizeof(RawClass*)));  // 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<RawClass**>(
        calloc(capacity_, sizeof(RawClass*)));  // NOLINT
    for (intptr_t i = kObjectCid; i < kInstanceCid; i++) {
      table_[i] = vm_class_table->At(i);
    }
    table_[kFreeListElement] = vm_class_table->At(kFreeListElement);
    table_[kNullCid] = vm_class_table->At(kNullCid);
    table_[kDynamicCid] = vm_class_table->At(kDynamicCid);
    table_[kVoidCid] = vm_class_table->At(kVoidCid);
  }
}


ClassTable::~ClassTable() {
  free(table_);
}


void ClassTable::Register(const Class& cls) {
  intptr_t index = cls.id();
  if (index != kIllegalCid) {
    ASSERT(index > 0);
    ASSERT(index < kNumPredefinedCids);
    ASSERT(table_[index] == 0);
    ASSERT(index < capacity_);
    table_[index] = cls.raw();
    if (HeapTrace::is_enabled()) {
      Isolate::Current()->heap()->trace()->TraceRegisterClass(cls);
    }
    // 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 table_entry = Object::builtin_vtables_[index];
    ASSERT((table_entry == 0) || (table_entry == cls_vtable));
    if (table_entry == 0) {
      Object::builtin_vtables_[index] = cls_vtable;
    }
  } else {
    if (top_ == capacity_) {
      // Grow the capacity of the class table.
      intptr_t new_capacity = capacity_ + capacity_increment_;
      RawClass** new_table = reinterpret_cast<RawClass**>(
          realloc(table_, new_capacity * sizeof(RawClass*)));  // NOLINT
      for (intptr_t i = capacity_; i < new_capacity; i++) {
        new_table[i] = NULL;
      }
      capacity_ = new_capacity;
      table_ = new_table;
    }
    ASSERT(top_ < capacity_);
    cls.set_id(top_);
    table_[top_] = cls.raw();
    if (HeapTrace::is_enabled()) {
      Isolate::Current()->heap()->trace()->TraceRegisterClass(cls);
    }
    top_++;  // Increment next index.
  }
}


void ClassTable::VisitObjectPointers(ObjectPointerVisitor* visitor) {
  ASSERT(visitor != NULL);
  visitor->VisitPointers(reinterpret_cast<RawObject**>(&table_[0]), top_);
}


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

  for (intptr_t i = 1; i < top_; i++) {
    cls = At(i);
    if (cls.raw() != reinterpret_cast<RawClass*>(0)) {
      name = cls.Name();
      OS::Print("%"Pd": %s\n", i, name.ToCString());
    }
  }
}

}  // namespace dart
