// Copyright 2015 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_HEAP_SCAVENGER_H_
#define V8_HEAP_SCAVENGER_H_

#include "src/heap/objects-visiting.h"
#include "src/heap/slot-set.h"
#include "src/heap/worklist.h"

namespace v8 {
namespace internal {

static const int kCopiedListSegmentSize = 64;
static const int kPromotionListSegmentSize = 64;

using AddressRange = std::pair<Address, Address>;
using CopiedList = Worklist<AddressRange, kCopiedListSegmentSize>;
using ObjectAndSize = std::pair<HeapObject*, int>;
using PromotionList = Worklist<ObjectAndSize, kPromotionListSegmentSize>;

// A list of copied ranges. Keeps the last consecutive range local and announces
// all other ranges to a global work list.
class CopiedRangesList {
 public:
  CopiedRangesList(CopiedList* copied_list, int task_id)
      : current_start_(nullptr),
        current_end_(nullptr),
        copied_list_(copied_list, task_id) {}

  ~CopiedRangesList() {
    CHECK_NULL(current_start_);
    CHECK_NULL(current_end_);
  }

  void Insert(HeapObject* object, int size) {
    const Address object_address = object->address();
    if (current_end_ != object_address) {
      if (current_start_ != nullptr) {
        copied_list_.Push(AddressRange(current_start_, current_end_));
      }
      current_start_ = object_address;
      current_end_ = current_start_ + size;
      return;
    }
    DCHECK_EQ(current_end_, object_address);
    current_end_ += size;
    return;
  }

  bool Pop(AddressRange* entry) {
    if (copied_list_.Pop(entry)) {
      return true;
    } else if (current_start_ != nullptr) {
      *entry = AddressRange(current_start_, current_end_);
      current_start_ = current_end_ = nullptr;
      return true;
    }
    return false;
  }

 private:
  Address current_start_;
  Address current_end_;
  CopiedList::View copied_list_;
};

class Scavenger {
 public:
  Scavenger(Heap* heap, bool is_logging, bool is_incremental_marking,
            CopiedList* copied_list, PromotionList* promotion_list, int task_id)
      : heap_(heap),
        promotion_list_(promotion_list, task_id),
        copied_list_(copied_list, task_id),
        is_logging_(is_logging),
        is_incremental_marking_(is_incremental_marking) {}

  // Scavenges an object |object| referenced from slot |p|. |object| is required
  // to be in from space.
  inline void ScavengeObject(HeapObject** p, HeapObject* object);

  // Potentially scavenges an object referenced from |slot_address| if it is
  // indeed a HeapObject and resides in from space.
  inline SlotCallbackResult CheckAndScavengeObject(Heap* heap,
                                                   Address slot_address);

  // Processes remaining work (=objects) after single objects have been
  // manually scavenged using ScavengeObject or CheckAndScavengeObject.
  void Process();

 private:
  inline Heap* heap() { return heap_; }

  V8_INLINE HeapObject* MigrateObject(HeapObject* source, HeapObject* target,
                                      int size);

  V8_INLINE bool SemiSpaceCopyObject(Map* map, HeapObject** slot,
                                     HeapObject* object, int object_size);

  V8_INLINE bool PromoteObject(Map* map, HeapObject** slot, HeapObject* object,
                               int object_size);

  V8_INLINE void EvacuateObject(HeapObject** slot, Map* map,
                                HeapObject* source);

  // Different cases for object evacuation.

  V8_INLINE void EvacuateObjectDefault(Map* map, HeapObject** slot,
                                       HeapObject* object, int object_size);

  V8_INLINE void EvacuateJSFunction(Map* map, HeapObject** slot,
                                    JSFunction* object, int object_size);

  inline void EvacuateThinString(Map* map, HeapObject** slot,
                                 ThinString* object, int object_size);

  inline void EvacuateShortcutCandidate(Map* map, HeapObject** slot,
                                        ConsString* object, int object_size);

  void IterateAndScavengePromotedObject(HeapObject* target, int size);

  void RecordCopiedObject(HeapObject* obj);

  Heap* const heap_;
  PromotionList::View promotion_list_;
  CopiedRangesList copied_list_;
  bool is_logging_;
  bool is_incremental_marking_;
};

// Helper class for turning the scavenger into an object visitor that is also
// filtering out non-HeapObjects and objects which do not reside in new space.
class RootScavengeVisitor final : public RootVisitor {
 public:
  RootScavengeVisitor(Heap* heap, Scavenger* scavenger)
      : heap_(heap), scavenger_(scavenger) {}

  void VisitRootPointer(Root root, Object** p) final;
  void VisitRootPointers(Root root, Object** start, Object** end) final;

 private:
  void ScavengePointer(Object** p);

  Heap* const heap_;
  Scavenger* const scavenger_;
};

class ScavengeVisitor final : public NewSpaceVisitor<ScavengeVisitor> {
 public:
  ScavengeVisitor(Heap* heap, Scavenger* scavenger)
      : heap_(heap), scavenger_(scavenger) {}

  V8_INLINE void VisitPointers(HeapObject* host, Object** start,
                               Object** end) final;

 private:
  Heap* const heap_;
  Scavenger* const scavenger_;
};

}  // namespace internal
}  // namespace v8

#endif  // V8_HEAP_SCAVENGER_H_
