// Copyright 2012 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_OBJECTS_VISITING_INL_H_
#define V8_OBJECTS_VISITING_INL_H_

#include "src/heap/objects-visiting.h"

#include "src/heap/array-buffer-tracker.h"
#include "src/heap/embedder-tracing.h"
#include "src/heap/mark-compact.h"
#include "src/macro-assembler.h"
#include "src/objects-body-descriptors-inl.h"

namespace v8 {
namespace internal {

template <typename ResultType, typename ConcreteVisitor>
ResultType HeapVisitor<ResultType, ConcreteVisitor>::Visit(HeapObject* object) {
  return Visit(object->map(), object);
}

template <typename ResultType, typename ConcreteVisitor>
ResultType HeapVisitor<ResultType, ConcreteVisitor>::Visit(Map* map,
                                                           HeapObject* object) {
  ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
  switch (static_cast<VisitorId>(map->visitor_id())) {
#define CASE(type)   \
  case kVisit##type: \
    return visitor->Visit##type(map, type::cast(object));
    TYPED_VISITOR_ID_LIST(CASE)
#undef CASE
    case kVisitShortcutCandidate:
      return visitor->VisitShortcutCandidate(map, ConsString::cast(object));
    case kVisitNativeContext:
      return visitor->VisitNativeContext(map, Context::cast(object));
    case kVisitDataObject:
      return visitor->VisitDataObject(map, HeapObject::cast(object));
    case kVisitJSObjectFast:
      return visitor->VisitJSObjectFast(map, JSObject::cast(object));
    case kVisitJSApiObject:
      return visitor->VisitJSApiObject(map, JSObject::cast(object));
    case kVisitStruct:
      return visitor->VisitStruct(map, HeapObject::cast(object));
    case kVisitFreeSpace:
      return visitor->VisitFreeSpace(map, FreeSpace::cast(object));
    case kVisitorIdCount:
      UNREACHABLE();
  }
  UNREACHABLE();
  // Make the compiler happy.
  return ResultType();
}

template <typename ResultType, typename ConcreteVisitor>
void HeapVisitor<ResultType, ConcreteVisitor>::VisitMapPointer(
    HeapObject* host, HeapObject** map) {
  static_cast<ConcreteVisitor*>(this)->VisitPointer(
      host, reinterpret_cast<Object**>(map));
}

#define VISIT(type)                                                 \
  template <typename ResultType, typename ConcreteVisitor>          \
  ResultType HeapVisitor<ResultType, ConcreteVisitor>::Visit##type( \
      Map* map, type* object) {                                     \
    ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this); \
    if (!visitor->ShouldVisit(object)) return ResultType();         \
    int size = type::BodyDescriptor::SizeOf(map, object);           \
    if (visitor->ShouldVisitMapPointer())                           \
      visitor->VisitMapPointer(object, object->map_slot());         \
    type::BodyDescriptor::IterateBody(object, size, visitor);       \
    return static_cast<ResultType>(size);                           \
  }
TYPED_VISITOR_ID_LIST(VISIT)
#undef VISIT

template <typename ResultType, typename ConcreteVisitor>
ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitShortcutCandidate(
    Map* map, ConsString* object) {
  ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
  if (!visitor->ShouldVisit(object)) return ResultType();
  int size = ConsString::BodyDescriptor::SizeOf(map, object);
  if (visitor->ShouldVisitMapPointer())
    visitor->VisitMapPointer(object, object->map_slot());
  ConsString::BodyDescriptor::IterateBody(object, size, visitor);
  return static_cast<ResultType>(size);
}

template <typename ResultType, typename ConcreteVisitor>
ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitNativeContext(
    Map* map, Context* object) {
  ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
  if (!visitor->ShouldVisit(object)) return ResultType();
  int size = Context::BodyDescriptor::SizeOf(map, object);
  if (visitor->ShouldVisitMapPointer())
    visitor->VisitMapPointer(object, object->map_slot());
  Context::BodyDescriptor::IterateBody(object, size, visitor);
  return static_cast<ResultType>(size);
}

template <typename ResultType, typename ConcreteVisitor>
ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitDataObject(
    Map* map, HeapObject* object) {
  ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
  if (!visitor->ShouldVisit(object)) return ResultType();
  int size = map->instance_size();
  if (visitor->ShouldVisitMapPointer())
    visitor->VisitMapPointer(object, object->map_slot());
  return static_cast<ResultType>(size);
}

template <typename ResultType, typename ConcreteVisitor>
ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitJSObjectFast(
    Map* map, JSObject* object) {
  ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
  if (!visitor->ShouldVisit(object)) return ResultType();
  int size = JSObject::FastBodyDescriptor::SizeOf(map, object);
  if (visitor->ShouldVisitMapPointer())
    visitor->VisitMapPointer(object, object->map_slot());
  JSObject::FastBodyDescriptor::IterateBody(object, size, visitor);
  return static_cast<ResultType>(size);
}

template <typename ResultType, typename ConcreteVisitor>
ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitJSApiObject(
    Map* map, JSObject* object) {
  ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
  if (!visitor->ShouldVisit(object)) return ResultType();
  int size = JSObject::BodyDescriptor::SizeOf(map, object);
  if (visitor->ShouldVisitMapPointer())
    visitor->VisitMapPointer(object, object->map_slot());
  JSObject::BodyDescriptor::IterateBody(object, size, visitor);
  return static_cast<ResultType>(size);
}

template <typename ResultType, typename ConcreteVisitor>
ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitStruct(
    Map* map, HeapObject* object) {
  ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
  if (!visitor->ShouldVisit(object)) return ResultType();
  int size = map->instance_size();
  if (visitor->ShouldVisitMapPointer())
    visitor->VisitMapPointer(object, object->map_slot());
  StructBodyDescriptor::IterateBody(object, size, visitor);
  return static_cast<ResultType>(size);
}

template <typename ResultType, typename ConcreteVisitor>
ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitFreeSpace(
    Map* map, FreeSpace* object) {
  ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
  if (!visitor->ShouldVisit(object)) return ResultType();
  if (visitor->ShouldVisitMapPointer())
    visitor->VisitMapPointer(object, object->map_slot());
  return static_cast<ResultType>(FreeSpace::cast(object)->size());
}

template <typename ConcreteVisitor>
int NewSpaceVisitor<ConcreteVisitor>::VisitJSFunction(Map* map,
                                                      JSFunction* object) {
  ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
  int size = JSFunction::BodyDescriptorWeak::SizeOf(map, object);
  JSFunction::BodyDescriptorWeak::IterateBody(object, size, visitor);
  return size;
}

template <typename ConcreteVisitor>
int NewSpaceVisitor<ConcreteVisitor>::VisitNativeContext(Map* map,
                                                         Context* object) {
  ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
  int size = Context::BodyDescriptor::SizeOf(map, object);
  Context::BodyDescriptor::IterateBody(object, size, visitor);
  return size;
}

template <typename ConcreteVisitor>
int NewSpaceVisitor<ConcreteVisitor>::VisitJSApiObject(Map* map,
                                                       JSObject* object) {
  ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
  return visitor->VisitJSObject(map, object);
}

template <typename ConcreteVisitor>
int MarkingVisitor<ConcreteVisitor>::VisitJSFunction(Map* map,
                                                     JSFunction* object) {
  ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
  int size = JSFunction::BodyDescriptorWeak::SizeOf(map, object);
  JSFunction::BodyDescriptorWeak::IterateBody(object, size, visitor);
  return size;
}

template <typename ConcreteVisitor>
int MarkingVisitor<ConcreteVisitor>::VisitTransitionArray(
    Map* map, TransitionArray* array) {
  ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
  int size = TransitionArray::BodyDescriptor::SizeOf(map, array);
  TransitionArray::BodyDescriptor::IterateBody(array, size, visitor);
  collector_->AddTransitionArray(array);
  return size;
}

template <typename ConcreteVisitor>
int MarkingVisitor<ConcreteVisitor>::VisitWeakCell(Map* map,
                                                   WeakCell* weak_cell) {
  // Enqueue weak cell in linked list of encountered weak collections.
  // We can ignore weak cells with cleared values because they will always
  // contain smi zero.
  if (!weak_cell->cleared()) {
    HeapObject* value = HeapObject::cast(weak_cell->value());
    if (heap_->incremental_marking()->marking_state()->IsBlackOrGrey(value)) {
      // Weak cells with live values are directly processed here to reduce
      // the processing time of weak cells during the main GC pause.
      Object** slot = HeapObject::RawField(weak_cell, WeakCell::kValueOffset);
      collector_->RecordSlot(weak_cell, slot, *slot);
    } else {
      // If we do not know about liveness of values of weak cells, we have to
      // process them when we know the liveness of the whole transitive
      // closure.
      collector_->AddWeakCell(weak_cell);
    }
  }
  return WeakCell::BodyDescriptor::SizeOf(map, weak_cell);
}

template <typename ConcreteVisitor>
int MarkingVisitor<ConcreteVisitor>::VisitNativeContext(Map* map,
                                                        Context* context) {
  ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
  int size = Context::BodyDescriptorWeak::SizeOf(map, context);
  Context::BodyDescriptorWeak::IterateBody(context, size, visitor);
  return size;
}

template <typename ConcreteVisitor>
int MarkingVisitor<ConcreteVisitor>::VisitJSWeakCollection(
    Map* map, JSWeakCollection* weak_collection) {
  ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);

  // Enqueue weak collection in linked list of encountered weak collections.
  if (weak_collection->next() == heap_->undefined_value()) {
    weak_collection->set_next(heap_->encountered_weak_collections());
    heap_->set_encountered_weak_collections(weak_collection);
  }

  // Skip visiting the backing hash table containing the mappings and the
  // pointer to the other enqueued weak collections, both are post-processed.
  int size = JSWeakCollection::BodyDescriptorWeak::SizeOf(map, weak_collection);
  JSWeakCollection::BodyDescriptorWeak::IterateBody(weak_collection, size,
                                                    visitor);

  // Partially initialized weak collection is enqueued, but table is ignored.
  if (!weak_collection->table()->IsHashTable()) return size;

  // Mark the backing hash table without pushing it on the marking stack.
  Object** slot =
      HeapObject::RawField(weak_collection, JSWeakCollection::kTableOffset);
  HeapObject* obj = HeapObject::cast(*slot);
  collector_->RecordSlot(weak_collection, slot, obj);
  visitor->MarkObjectWithoutPush(weak_collection, obj);
  return size;
}

template <typename ConcreteVisitor>
int MarkingVisitor<ConcreteVisitor>::VisitBytecodeArray(Map* map,
                                                        BytecodeArray* array) {
  ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
  int size = BytecodeArray::BodyDescriptor::SizeOf(map, array);
  BytecodeArray::BodyDescriptor::IterateBody(array, size, visitor);
  array->MakeOlder();
  return size;
}

template <typename ConcreteVisitor>
int MarkingVisitor<ConcreteVisitor>::VisitCode(Map* map, Code* code) {
  ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
  int size = Code::BodyDescriptor::SizeOf(map, code);
  Code::BodyDescriptor::IterateBody(code, size, visitor);
  return size;
}

template <typename ConcreteVisitor>
void MarkingVisitor<ConcreteVisitor>::MarkMapContents(Map* map) {
  ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
  // Since descriptor arrays are potentially shared, ensure that only the
  // descriptors that belong to this map are marked. The first time a non-empty
  // descriptor array is marked, its header is also visited. The slot holding
  // the descriptor array will be implicitly recorded when the pointer fields of
  // this map are visited.  Prototype maps don't keep track of transitions, so
  // just mark the entire descriptor array.
  if (!map->is_prototype_map()) {
    DescriptorArray* descriptors = map->instance_descriptors();
    if (visitor->MarkObjectWithoutPush(map, descriptors) &&
        descriptors->length() > 0) {
      visitor->VisitPointers(descriptors, descriptors->GetFirstElementAddress(),
                             descriptors->GetDescriptorEndSlot(0));
    }
    int start = 0;
    int end = map->NumberOfOwnDescriptors();
    if (start < end) {
      visitor->VisitPointers(descriptors,
                             descriptors->GetDescriptorStartSlot(start),
                             descriptors->GetDescriptorEndSlot(end));
    }
  }

  // Mark the pointer fields of the Map. Since the transitions array has
  // been marked already, it is fine that one of these fields contains a
  // pointer to it.
  visitor->VisitPointers(
      map, HeapObject::RawField(map, Map::kPointerFieldsBeginOffset),
      HeapObject::RawField(map, Map::kPointerFieldsEndOffset));
}

template <typename ConcreteVisitor>
int MarkingVisitor<ConcreteVisitor>::VisitMap(Map* map, Map* object) {
  ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);

  // When map collection is enabled we have to mark through map's transitions
  // and back pointers in a special way to make these links weak.
  if (object->CanTransition()) {
    MarkMapContents(object);
  } else {
    visitor->VisitPointers(
        object, HeapObject::RawField(object, Map::kPointerFieldsBeginOffset),
        HeapObject::RawField(object, Map::kPointerFieldsEndOffset));
  }
  return Map::BodyDescriptor::SizeOf(map, object);
}

template <typename ConcreteVisitor>
int MarkingVisitor<ConcreteVisitor>::VisitJSApiObject(Map* map,
                                                      JSObject* object) {
  ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
  if (heap_->local_embedder_heap_tracer()->InUse()) {
    DCHECK(object->IsJSObject());
    heap_->TracePossibleWrapper(object);
  }
  int size = JSObject::BodyDescriptor::SizeOf(map, object);
  JSObject::BodyDescriptor::IterateBody(object, size, visitor);
  return size;
}

template <typename ConcreteVisitor>
int MarkingVisitor<ConcreteVisitor>::VisitAllocationSite(
    Map* map, AllocationSite* object) {
  ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
  int size = AllocationSite::BodyDescriptorWeak::SizeOf(map, object);
  AllocationSite::BodyDescriptorWeak::IterateBody(object, size, visitor);
  return size;
}

template <typename ConcreteVisitor>
void MarkingVisitor<ConcreteVisitor>::VisitEmbeddedPointer(Code* host,
                                                           RelocInfo* rinfo) {
  ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
  DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
  HeapObject* object = HeapObject::cast(rinfo->target_object());
  collector_->RecordRelocSlot(host, rinfo, object);
  if (!host->IsWeakObject(object)) {
    visitor->MarkObject(host, object);
  }
}

template <typename ConcreteVisitor>
void MarkingVisitor<ConcreteVisitor>::VisitCodeTarget(Code* host,
                                                      RelocInfo* rinfo) {
  ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
  DCHECK(RelocInfo::IsCodeTarget(rinfo->rmode()));
  Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
  collector_->RecordRelocSlot(host, rinfo, target);
  visitor->MarkObject(host, target);
}

}  // namespace internal
}  // namespace v8

#endif  // V8_OBJECTS_VISITING_INL_H_
