// Copyright 2011 Google Inc. All Rights Reserved.

#include "mark_sweep.h"

#include <climits>
#include <vector>

#include "heap.h"
#include "logging.h"
#include "macros.h"
#include "mark_stack.h"
#include "object.h"
#include "space.h"
#include "thread.h"

namespace art {

size_t MarkSweep::reference_referent_offset_ = 0;  // TODO
size_t MarkSweep::reference_queue_offset_ = 0;  // TODO
size_t MarkSweep::reference_queueNext_offset_ = 0;  // TODO
size_t MarkSweep::reference_pendingNext_offset_ = 0;  // TODO
size_t MarkSweep::finalizer_reference_zombie_offset_ = 0;  // TODO

bool MarkSweep::Init() {
  mark_stack_ = MarkStack::Create();
  if (mark_stack_ == NULL) {
    return false;
  }

  mark_bitmap_ = Heap::GetMarkBits();
  live_bitmap_ = Heap::GetLiveBits();

  // TODO: if concurrent, clear the card table.

  // TODO: check that the mark bitmap is entirely clear.

  return true;
}

void MarkSweep::MarkObject0(const Object* obj, bool check_finger) {
  DCHECK(obj != NULL);
  if (obj < condemned_) {
    DCHECK(IsMarked(obj));
    return;
  }
  bool is_marked = mark_bitmap_->Test(obj);
  // This object was not previously marked.
  if (!is_marked) {
    mark_bitmap_->Set(obj);
    if (check_finger && obj < finger_) {
      // The object must be pushed on to the mark stack.
      mark_stack_->Push(obj);
    }
  }
}

// Used to mark objects when recursing.  Recursion is done by moving
// the finger across the bitmaps in address order and marking child
// objects.  Any newly-marked objects whose addresses are lower than
// the finger won't be visited by the bitmap scan, so those objects
// need to be added to the mark stack.
void MarkSweep::MarkObject(const Object* obj) {
  if (obj != NULL) {
    MarkObject0(obj, true);
  }
}

// Marks all objects in the root set.
void MarkSweep::MarkRoots() {
  UNIMPLEMENTED(FATAL);
}

void MarkSweep::ScanBitmapCallback(Object* obj, void* finger, void* arg) {
  MarkSweep* mark_sweep = reinterpret_cast<MarkSweep*>(arg);
  mark_sweep->finger_ = reinterpret_cast<Object*>(finger);
  mark_sweep->ScanObject(obj);
}

// Populates the mark stack based on the set of marked objects and
// recursively marks until the mark stack is emptied.
void MarkSweep::RecursiveMark() {
  void* arg = reinterpret_cast<void*>(this);
  const std::vector<Space*>& spaces = Heap::GetSpaces();
  for (size_t i = 0; i < spaces.size(); ++i) {
    if (spaces[i]->IsCondemned()) {
      uintptr_t base = reinterpret_cast<uintptr_t>(spaces[i]->GetBase());
      uintptr_t limit = reinterpret_cast<uintptr_t>(spaces[i]->GetLimit());
      mark_bitmap_->ScanWalk(base, limit, &MarkSweep::ScanBitmapCallback, arg);
    }
  }
  finger_ = reinterpret_cast<Object*>(~0);
  ProcessMarkStack();
}

void MarkSweep::ReMarkRoots() {
  UNIMPLEMENTED(FATAL);
}

void MarkSweep::SweepSystemWeaks() {
  UNIMPLEMENTED(FATAL);
}

void MarkSweep::SweepCallback(size_t num_ptrs, void **ptrs, void *arg) {
  // TODO, lock heap if concurrent
  Space* space = static_cast<Space*>(arg);
  for (size_t i = 0; i < num_ptrs; ++i) {
    Object* obj = static_cast<Object*>(ptrs[i]);
    space->Free(obj);
  }
  // TODO, unlock heap if concurrent
}

void MarkSweep::Sweep() {
  const std::vector<Space*>& spaces = Heap::GetSpaces();
  for (size_t i = 0; i < spaces.size(); ++i) {
    if (spaces[i]->IsCondemned()) {
      uintptr_t base = reinterpret_cast<uintptr_t>(spaces[i]->GetBase());
      uintptr_t limit = reinterpret_cast<uintptr_t>(spaces[i]->GetLimit());
      void* arg = static_cast<void*>(spaces[i]);
      HeapBitmap::SweepWalk(*live_bitmap_, *mark_bitmap_, base, limit,
                            &MarkSweep::SweepCallback, arg);
    }
  }
}

// Scans instance fields.
void MarkSweep::ScanInstanceFields(const Object* obj) {
  DCHECK(obj != NULL);
  Class* klass = obj->GetClass();
  DCHECK(klass != NULL);
  ScanFields(obj,
             klass->GetReferenceInstanceOffsets(),
             false);
}

// Scans static storage on a Class.
void MarkSweep::ScanStaticFields(const Class* klass) {
  DCHECK(klass != NULL);
  ScanFields(klass,
             klass->GetReferenceStaticOffsets(),
             true);
}

void MarkSweep::ScanFields(const Object* obj,
                           uint32_t ref_offsets,
                           bool is_static) {
  if (ref_offsets != CLASS_WALK_SUPER) {
    // Found a reference offset bitmap.  Mark the specified offsets.
    while (ref_offsets != 0) {
      size_t right_shift = CLZ(ref_offsets);
      size_t byte_offset = CLASS_OFFSET_FROM_CLZ(right_shift);
      const Object* ref = obj->GetFieldObject(byte_offset);
      MarkObject(ref);
      ref_offsets &= ~(CLASS_HIGH_BIT >> right_shift);
    }
  } else {
    // There is no reference offset bitmap.  In the non-static case,
    // walk up the class inheritance hierarchy and find reference
    // offsets the hard way. In the static case, just consider this
    // class.
    for (const Class* klass = is_static ? obj->AsClass() : obj->GetClass();
         klass != NULL;
         klass = is_static ? NULL : klass->GetSuperClass()) {
      size_t num_reference_fields = (is_static
                                     ? klass->NumReferenceStaticFields()
                                     : klass->NumReferenceInstanceFields());
      for (size_t i = 0; i < num_reference_fields; ++i) {
        Field* field = (is_static
                        ? klass->GetStaticField(i)
                        : klass->GetInstanceField(i));
        size_t field_offset = field->GetOffset();
        const Object* ref = obj->GetFieldObject(field_offset);
        MarkObject(ref);
      }
    }
  }
}

void MarkSweep::ScanInterfaces(const Class* klass) {
  DCHECK(klass != NULL);
  for (size_t i = 0; i < klass->NumInterfaces(); ++i) {
    MarkObject(klass->GetInterface(i));
  }
}

// Scans the header, static field references, and interface pointers
// of a class object.
void MarkSweep::ScanClass(const Object* obj) {
  DCHECK(obj != NULL);
  DCHECK(obj->IsClass());
  const Class* klass = obj->AsClass();
  MarkObject(klass->GetClass());
  if (klass->IsArray()) {
    MarkObject(klass->GetComponentType());
  }
  if (klass->IsLoaded()) {
    MarkObject(klass->GetSuperClass());
  }
  MarkObject(klass->GetClassLoader());
  ScanInstanceFields(obj);
  ScanStaticFields(klass);
  // TODO: scan methods
  // TODO: scan instance fields
  if (klass->IsLoaded()) {
    ScanInterfaces(klass);
  }
}

// Scans the header of all array objects.  If the array object is
// specialized to a reference type, scans the array data as well.
void MarkSweep::ScanArray(const Object* obj) {
  DCHECK(obj != NULL);
  DCHECK(obj->GetClass() != NULL);
  MarkObject(obj->GetClass());
  if (obj->IsObjectArray()) {
    const ObjectArray<Object>* array = obj->AsObjectArray<Object>();
    for (int32_t i = 0; i < array->GetLength(); ++i) {
      const Object* element = array->Get(i);
      MarkObject(element);
    }
  }
}

void MarkSweep::EnqueuePendingReference(Object* ref, Object** list) {
  DCHECK(ref != NULL);
  DCHECK(list != NULL);
  size_t offset = reference_pendingNext_offset_;
  if (*list == NULL) {
    ref->SetFieldObject(offset, ref);
    *list = ref;
  } else {
    Object* head = (*list)->GetFieldObject(offset);
    ref->SetFieldObject(offset, head);
    (*list)->SetFieldObject(offset, ref);
  }
}

Object* MarkSweep::DequeuePendingReference(Object** list) {
  DCHECK(list != NULL);
  DCHECK(*list != NULL);
  size_t offset = reference_pendingNext_offset_;
  Object* head = (*list)->GetFieldObject(offset);
  Object* ref;
  if (*list == head) {
    ref = *list;
    *list = NULL;
  } else {
    Object* next = head->GetFieldObject(offset);
    (*list)->SetFieldObject(offset, next);
    ref = head;
  }
  ref->SetFieldObject(offset, NULL);
  return ref;
}

// Process the "referent" field in a java.lang.ref.Reference.  If the
// referent has not yet been marked, put it on the appropriate list in
// the gcHeap for later processing.
void MarkSweep::DelayReferenceReferent(Object* obj) {
  DCHECK(obj != NULL);
  DCHECK(obj->GetClass() != NULL);
  DCHECK(obj->IsReference());
  Object* pending = obj->GetFieldObject(reference_pendingNext_offset_);
  Object* referent = obj->GetFieldObject(reference_referent_offset_);
  if (pending == NULL && referent != NULL && !IsMarked(referent)) {
    Object** list = NULL;
    if (obj->IsSoftReference()) {
      list = &soft_reference_list_;
    } else if (obj->IsWeakReference()) {
      list = &weak_reference_list_;
    } else if (obj->IsFinalizerReference()) {
      list = &finalizer_reference_list_;
    } else if (obj->IsPhantomReference()) {
      list = &phantom_reference_list_;
    }
    DCHECK(list != NULL);
    EnqueuePendingReference(obj, list);
  }
}

// Scans the header and field references of a data object.  If the
// scanned object is a reference subclass, it is scheduled for later
// processing
void MarkSweep::ScanOther(const Object* obj) {
  DCHECK(obj != NULL);
  DCHECK(obj->GetClass() != NULL);
  MarkObject(obj->GetClass());
  ScanInstanceFields(obj);
  if (obj->IsReference()) {
    DelayReferenceReferent(const_cast<Object*>(obj));
  }
}

// Scans an object reference.  Determines the type of the reference
// and dispatches to a specialized scanning routine.
void MarkSweep::ScanObject(const Object* obj) {
  DCHECK(obj != NULL);
  DCHECK(obj->GetClass() != NULL);
  DCHECK(IsMarked(obj));
  if (obj->IsClass()) {
    ScanClass(obj);
  } else if (obj->IsArray()) {
    ScanArray(obj);
  } else {
    ScanOther(obj);
  }
}

// Scan anything that's on the mark stack.  We can't use the bitmaps
// anymore, so use a finger that points past the end of them.
void MarkSweep::ProcessMarkStack() {
  while (!mark_stack_->IsEmpty()) {
    const Object* obj = mark_stack_->Pop();
    ScanObject(obj);
  }
}

void MarkSweep::ScanDirtyObjects() {
  ProcessMarkStack();
}

void MarkSweep::ClearReference(Object* ref) {
  DCHECK(ref != NULL);
  ref->SetFieldObject(reference_referent_offset_, NULL);
}

bool MarkSweep::IsEnqueuable(const Object* ref) {
  DCHECK(ref != NULL);
  const Object* queue = ref->GetFieldObject(reference_queue_offset_);
  const Object* queue_next = ref->GetFieldObject(reference_queueNext_offset_);
  return (queue != NULL) && (queue_next == NULL);
}

void MarkSweep::EnqueueReference(Object* ref) {
  DCHECK(ref != NULL);
  CHECK(ref->GetFieldObject(reference_queue_offset_) != NULL);
  CHECK(ref->GetFieldObject(reference_queueNext_offset_) == NULL);
  EnqueuePendingReference(ref, &cleared_reference_list_);
}

// Walks the reference list marking any references subject to the
// reference clearing policy.  References with a black referent are
// removed from the list.  References with white referents biased
// toward saving are blackened and also removed from the list.
void MarkSweep::PreserveSomeSoftReferences(Object** list) {
  DCHECK(list != NULL);
  Object* clear = NULL;
  size_t counter = 0;
  while (*list != NULL) {
    Object* ref = DequeuePendingReference(list);
    Object* referent = ref->GetFieldObject(reference_referent_offset_);
    if (referent == NULL) {
      // Referent was cleared by the user during marking.
      continue;
    }
    bool is_marked = IsMarked(referent);
    if (!is_marked && ((++counter) & 1)) {
      // Referent is white and biased toward saving, mark it.
      MarkObject(referent);
      is_marked = true;
    }
    if (!is_marked) {
      // Referent is white, queue it for clearing.
      EnqueuePendingReference(ref, &clear);
    }
  }
  *list = clear;
  // Restart the mark with the newly black references added to the
  // root set.
  ProcessMarkStack();
}

// Unlink the reference list clearing references objects with white
// referents.  Cleared references registered to a reference queue are
// scheduled for appending by the heap worker thread.
void MarkSweep::ClearWhiteReferences(Object** list) {
  DCHECK(list != NULL);
  size_t offset = reference_referent_offset_;
  while (*list != NULL) {
    Object* ref = DequeuePendingReference(list);
    Object* referent = ref->GetFieldObject(offset);
    if (referent != NULL && !IsMarked(referent)) {
      // Referent is white, clear it.
      ClearReference(ref);
      if (IsEnqueuable(ref)) {
        EnqueueReference(ref);
      }
    }
  }
  DCHECK(*list == NULL);
}

// Enqueues finalizer references with white referents.  White
// referents are blackened, moved to the zombie field, and the
// referent field is cleared.
void MarkSweep::EnqueueFinalizerReferences(Object** list) {
  DCHECK(list != NULL);
  size_t referent_offset = reference_referent_offset_;
  size_t zombie_offset = finalizer_reference_zombie_offset_;
  bool has_enqueued = false;
  while (*list != NULL) {
    Object* ref = DequeuePendingReference(list);
    Object* referent = ref->GetFieldObject(referent_offset);
    if (referent != NULL && !IsMarked(referent)) {
      MarkObject(referent);
      // If the referent is non-null the reference must queuable.
      DCHECK(IsEnqueuable(ref));
      ref->SetFieldObject(zombie_offset, referent);
      ClearReference(ref);
      EnqueueReference(ref);
      has_enqueued = true;
    }
  }
  if (has_enqueued) {
    ProcessMarkStack();
  }
  DCHECK(*list == NULL);
}

// Process reference class instances and schedule finalizations.
void MarkSweep::ProcessReferences(Object** soft_references, bool clear_soft,
                                  Object** weak_references,
                                  Object** finalizer_references,
                                  Object** phantom_references) {
  DCHECK(soft_references != NULL);
  DCHECK(weak_references != NULL);
  DCHECK(finalizer_references != NULL);
  DCHECK(phantom_references != NULL);

  // Unless we are in the zygote or required to clear soft references
  // with white references, preserve some white referents.
  if (clear_soft) {
    PreserveSomeSoftReferences(soft_references);
  }

  // Clear all remaining soft and weak references with white
  // referents.
  ClearWhiteReferences(soft_references);
  ClearWhiteReferences(weak_references);

  // Preserve all white objects with finalize methods and schedule
  // them for finalization.
  EnqueueFinalizerReferences(finalizer_references);

  // Clear all f-reachable soft and weak references with white
  // referents.
  ClearWhiteReferences(soft_references);
  ClearWhiteReferences(weak_references);

  // Clear all phantom references with white referents.
  ClearWhiteReferences(phantom_references);

  // At this point all reference lists should be empty.
  DCHECK(*soft_references == NULL);
  DCHECK(*weak_references == NULL);
  DCHECK(*finalizer_references == NULL);
  DCHECK(*phantom_references == NULL);
}

// Pushes a list of cleared references out to the managed heap.
void MarkSweep::EnqueueClearedReferences(Object** cleared) {
  DCHECK(cleared != NULL);
  if (*cleared != NULL) {
    Thread* self = Thread::Current();
    DCHECK(self != NULL);
    // TODO: Method *meth = gDvm.methJavaLangRefReferenceQueueAdd;
    // DCHECK(meth != NULL);
    // JValue unused;
    // Object* reference = *cleared;
    // TODO: dvmCallMethod(self, meth, NULL, &unused, reference);
    UNIMPLEMENTED(FATAL);
    *cleared = NULL;
  }
}

MarkSweep::~MarkSweep() {
  delete mark_stack_;
  mark_bitmap_->Clear();
}

}  // namespace art
