// 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.

#ifndef RUNTIME_VM_HEAP_SCAVENGER_H_
#define RUNTIME_VM_HEAP_SCAVENGER_H_

#include "platform/assert.h"
#include "platform/utils.h"

#include "vm/dart.h"
#include "vm/flags.h"
#include "vm/globals.h"
#include "vm/heap/spaces.h"
#include "vm/isolate.h"
#include "vm/lockers.h"
#include "vm/raw_object.h"
#include "vm/ring_buffer.h"
#include "vm/virtual_memory.h"
#include "vm/visitor.h"

namespace dart {

// Forward declarations.
class Heap;
class Isolate;
class JSONObject;
class ObjectSet;
template <bool parallel>
class ScavengerVisitorBase;

static constexpr intptr_t kNewPageSize = 512 * KB;
static constexpr intptr_t kNewPageSizeInWords = kNewPageSize / kWordSize;
static constexpr intptr_t kNewPageMask = ~(kNewPageSize - 1);

// A page containing new generation objects.
class NewPage {
 public:
  static NewPage* Allocate();
  void Deallocate();

  uword start() const { return memory_->start(); }
  uword end() const { return memory_->end(); }
  bool Contains(uword addr) const { return memory_->Contains(addr); }
  void WriteProtect(bool read_only) {
    memory_->Protect(read_only ? VirtualMemory::kReadOnly
                               : VirtualMemory::kReadWrite);
  }

  NewPage* next() const { return next_; }
  void set_next(NewPage* next) { next_ = next; }

  Thread* owner() const { return owner_; }

  uword object_start() const { return start() + ObjectStartOffset(); }
  uword object_end() const { return owner_ != nullptr ? owner_->top() : top_; }
  void VisitObjects(ObjectVisitor* visitor) const {
    uword addr = object_start();
    uword end = object_end();
    while (addr < end) {
      ObjectPtr obj = UntaggedObject::FromAddr(addr);
      visitor->VisitObject(obj);
      addr += obj->untag()->HeapSize();
    }
  }
  void VisitObjectPointers(ObjectPointerVisitor* visitor) const {
    uword addr = object_start();
    uword end = object_end();
    while (addr < end) {
      ObjectPtr obj = UntaggedObject::FromAddr(addr);
      intptr_t size = obj->untag()->VisitPointers(visitor);
      addr += size;
    }
  }

  static intptr_t ObjectStartOffset() {
    return Utils::RoundUp(sizeof(NewPage), kObjectAlignment) +
           kNewObjectAlignmentOffset;
  }

  static NewPage* Of(ObjectPtr obj) {
    ASSERT(obj->IsHeapObject());
    ASSERT(obj->IsNewObject());
    return Of(static_cast<uword>(obj));
  }
  static NewPage* Of(uword addr) {
    return reinterpret_cast<NewPage*>(addr & kNewPageMask);
  }

  // Remember the limit to which objects have been copied.
  void RecordSurvivors() { survivor_end_ = object_end(); }

  // Move survivor end to the end of the to_ space, making all surviving
  // objects candidates for promotion next time.
  void EarlyTenure() { survivor_end_ = end_; }

  uword promo_candidate_words() const {
    return (survivor_end_ - object_start()) / kWordSize;
  }

  void Acquire(Thread* thread) {
    ASSERT(owner_ == nullptr);
    owner_ = thread;
    thread->set_top(top_);
    thread->set_end(end_);
  }
  void Release(Thread* thread) {
    ASSERT(owner_ == thread);
    owner_ = nullptr;
    top_ = thread->top();
    thread->set_top(0);
    thread->set_end(0);
  }
  void Release() {
    if (owner_ != nullptr) {
      Release(owner_);
    }
  }

  uword TryAllocateGC(intptr_t size) {
    ASSERT(owner_ == nullptr);
    uword result = top_;
    uword new_top = result + size;
    if (LIKELY(new_top <= end_)) {
      top_ = new_top;
      return result;
    }
    return 0;
  }

  void Unallocate(uword addr, intptr_t size) {
    ASSERT((addr + size) == top_);
    top_ -= size;
  }

  bool IsSurvivor(uword raw_addr) const { return raw_addr < survivor_end_; }
  bool IsResolved() const { return top_ == resolved_top_; }

 private:
  VirtualMemory* memory_;
  NewPage* next_;

  // The thread using this page for allocation, otherwise NULL.
  Thread* owner_;

  // The address of the next allocation. If owner is non-NULL, this value is
  // stale and the current value is at owner->top_. Called "NEXT" in the
  // original Cheney paper.
  uword top_;

  // The address after the last allocatable byte in this page.
  uword end_;

  // Objects below this address have survived a scavenge.
  uword survivor_end_;

  // A pointer to the first unprocessed object. Resolution completes when this
  // value meets the allocation top. Called "SCAN" in the original Cheney paper.
  uword resolved_top_;

  template <bool>
  friend class ScavengerVisitorBase;

  DISALLOW_ALLOCATION();
  DISALLOW_IMPLICIT_CONSTRUCTORS(NewPage);
};

class SemiSpace {
 public:
  static void Init();
  static void DrainCache();
  static void Cleanup();
  static intptr_t CachedSize();

  explicit SemiSpace(intptr_t max_capacity_in_words);
  ~SemiSpace();

  NewPage* TryAllocatePageLocked(bool link);

  bool Contains(uword addr) const;
  void WriteProtect(bool read_only);

  intptr_t capacity_in_words() const { return capacity_in_words_; }
  intptr_t max_capacity_in_words() const { return max_capacity_in_words_; }

  NewPage* head() const { return head_; }

  void AddList(NewPage* head, NewPage* tail);

 private:
  // Size of NewPages in this semi-space.
  intptr_t capacity_in_words_ = 0;

  // Size of NewPages before we trigger a scavenge.
  intptr_t max_capacity_in_words_;

  NewPage* head_ = nullptr;
  NewPage* tail_ = nullptr;
};

// Statistics for a particular scavenge.
class ScavengeStats {
 public:
  ScavengeStats() {}
  ScavengeStats(int64_t start_micros,
                int64_t end_micros,
                SpaceUsage before,
                SpaceUsage after,
                intptr_t promo_candidates_in_words,
                intptr_t promoted_in_words,
                intptr_t abandoned_in_words)
      : start_micros_(start_micros),
        end_micros_(end_micros),
        before_(before),
        after_(after),
        promo_candidates_in_words_(promo_candidates_in_words),
        promoted_in_words_(promoted_in_words),
        abandoned_in_words_(abandoned_in_words) {}

  // Of all data before scavenge, what fraction was found to be garbage?
  // If this scavenge included growth, assume the extra capacity would become
  // garbage to give the scavenger a chance to stablize at the new capacity.
  double ExpectedGarbageFraction() const {
    double work =
        after_.used_in_words + promoted_in_words_ + abandoned_in_words_;
    return 1.0 - (work / after_.capacity_in_words);
  }

  // Fraction of promotion candidates that survived and was thereby promoted.
  // Returns zero if there were no promotion candidates.
  double PromoCandidatesSuccessFraction() const {
    return promo_candidates_in_words_ > 0
               ? promoted_in_words_ /
                     static_cast<double>(promo_candidates_in_words_)
               : 0.0;
  }

  intptr_t UsedBeforeInWords() const { return before_.used_in_words; }

  int64_t DurationMicros() const { return end_micros_ - start_micros_; }

 private:
  int64_t start_micros_;
  int64_t end_micros_;
  SpaceUsage before_;
  SpaceUsage after_;
  intptr_t promo_candidates_in_words_;
  intptr_t promoted_in_words_;
  intptr_t abandoned_in_words_;
};

class Scavenger {
 private:
  static const intptr_t kTLABSize = 512 * KB;

 public:
  Scavenger(Heap* heap, intptr_t max_semi_capacity_in_words);
  ~Scavenger();

  // Check whether this Scavenger contains this address.
  // During scavenging both the to and from spaces contain "legal" objects.
  // During a scavenge this function only returns true for addresses that will
  // be part of the surviving objects.
  bool Contains(uword addr) const { return to_->Contains(addr); }

  ObjectPtr FindObject(FindObjectVisitor* visitor);

  uword TryAllocate(Thread* thread, intptr_t size) {
    uword addr = TryAllocateFromTLAB(thread, size);
    if (LIKELY(addr != 0)) {
      return addr;
    }
    TryAllocateNewTLAB(thread, size);
    return TryAllocateFromTLAB(thread, size);
  }
  void AbandonRemainingTLAB(Thread* thread);
  void AbandonRemainingTLABForDebugging(Thread* thread);

  // Collect the garbage in this scavenger.
  void Scavenge(GCReason reason);

  // Promote all live objects.
  void Evacuate(GCReason reason);

  int64_t UsedInWords() const {
    MutexLocker ml(&space_lock_);
    return to_->capacity_in_words();
  }
  int64_t CapacityInWords() const { return to_->max_capacity_in_words(); }
  int64_t ExternalInWords() const { return external_size_ >> kWordSizeLog2; }
  SpaceUsage GetCurrentUsage() const {
    SpaceUsage usage;
    usage.used_in_words = UsedInWords();
    usage.capacity_in_words = CapacityInWords();
    usage.external_in_words = ExternalInWords();
    return usage;
  }

  void VisitObjects(ObjectVisitor* visitor) const;
  void VisitObjectPointers(ObjectPointerVisitor* visitor) const;

  void AddRegionsToObjectSet(ObjectSet* set) const;

  void WriteProtect(bool read_only);

  bool ShouldPerformIdleScavenge(int64_t deadline);

  void AddGCTime(int64_t micros) { gc_time_micros_ += micros; }

  int64_t gc_time_micros() const { return gc_time_micros_; }

  void IncrementCollections() { collections_++; }

  intptr_t collections() const { return collections_; }

#ifndef PRODUCT
  void PrintToJSONObject(JSONObject* object) const;
#endif  // !PRODUCT

  void AllocatedExternal(intptr_t size) {
    ASSERT(size >= 0);
    external_size_ += size;
    ASSERT(external_size_ >= 0);
  }
  void FreedExternal(intptr_t size) {
    ASSERT(size >= 0);
    external_size_ -= size;
    ASSERT(external_size_ >= 0);
  }

  void MakeNewSpaceIterable();
  int64_t FreeSpaceInWords(Isolate* isolate) const;

  void InitGrowthControl() {
    growth_control_ = true;
  }

  void SetGrowthControlState(bool state) {
    growth_control_ = state;
  }

  bool GrowthControlState() { return growth_control_; }

  bool scavenging() const { return scavenging_; }

  // The maximum number of Dart mutator threads we allow to execute at the same
  // time.
  static intptr_t MaxMutatorThreadCount() {
    // With a max new-space of 16 MB and 512kb TLABs we would allow up to 8
    // mutator threads to run at the same time.
    const intptr_t max_parallel_tlab_usage =
        (FLAG_new_gen_semi_max_size * MB) / Scavenger::kTLABSize;
    const intptr_t max_pool_size = max_parallel_tlab_usage / 4;
    return max_pool_size > 0 ? max_pool_size : 1;
  }

  NewPage* head() const { return to_->head(); }

 private:
  // Ids for time and data records in Heap::GCStats.
  enum {
    // Time
    kDummyScavengeTime = 0,
    kSafePoint = 1,
    kVisitIsolateRoots = 2,
    kIterateStoreBuffers = 3,
    kProcessToSpace = 4,
    kIterateWeaks = 5,
  };

  uword TryAllocateFromTLAB(Thread* thread, intptr_t size) {
    ASSERT(Utils::IsAligned(size, kObjectAlignment));
    ASSERT(heap_ != Dart::vm_isolate_group()->heap());

    const uword result = thread->top();
    const intptr_t remaining = thread->end() - result;
    if (UNLIKELY(remaining < size)) {
      return 0;
    }

    ASSERT(to_->Contains(result));
    ASSERT((result & kObjectAlignmentMask) == kNewObjectAlignmentOffset);
    thread->set_top(result + size);
    return result;
  }
  void TryAllocateNewTLAB(Thread* thread, intptr_t size);

  SemiSpace* Prologue(GCReason reason);
  intptr_t ParallelScavenge(SemiSpace* from);
  intptr_t SerialScavenge(SemiSpace* from);
  void ReverseScavenge(SemiSpace** from);
  void IterateIsolateRoots(ObjectPointerVisitor* visitor);
  template <bool parallel>
  void IterateStoreBuffers(ScavengerVisitorBase<parallel>* visitor);
  template <bool parallel>
  void IterateRememberedCards(ScavengerVisitorBase<parallel>* visitor);
  void IterateObjectIdTable(ObjectPointerVisitor* visitor);
  template <bool parallel>
  void IterateRoots(ScavengerVisitorBase<parallel>* visitor);
  void MournWeakHandles();
  void Epilogue(SemiSpace* from);

  bool IsUnreachable(ObjectPtr* p);

  void VerifyStoreBuffers();

  void UpdateMaxHeapCapacity();
  void UpdateMaxHeapUsage();

  void MournWeakTables();

  intptr_t NewSizeInWords(intptr_t old_size_in_words, GCReason reason) const;

  Heap* heap_;

  SemiSpace* to_;

  PromotionStack promotion_stack_;

  intptr_t max_semi_capacity_in_words_;

  // Keep track whether a scavenge is currently running.
  bool scavenging_;
  bool early_tenure_ = false;
  RelaxedAtomic<intptr_t> root_slices_started_;
  StoreBufferBlock* blocks_ = nullptr;

  int64_t gc_time_micros_;
  intptr_t collections_;
  static const int kStatsHistoryCapacity = 4;
  RingBuffer<ScavengeStats, kStatsHistoryCapacity> stats_history_;

  intptr_t scavenge_words_per_micro_;
  intptr_t idle_scavenge_threshold_in_words_;

  // The total size of external data associated with objects in this scavenger.
  RelaxedAtomic<intptr_t> external_size_;

  RelaxedAtomic<bool> failed_to_promote_;
  RelaxedAtomic<bool> abort_;

  // When the isolate group is ready it will enable growth control via
  // InitGrowthControl.
  bool growth_control_ = false;

  // Protects new space during the allocation of new TLABs
  mutable Mutex space_lock_;

  template <bool>
  friend class ScavengerVisitorBase;
  friend class ScavengerWeakVisitor;

  DISALLOW_COPY_AND_ASSIGN(Scavenger);
};

}  // namespace dart

#endif  // RUNTIME_VM_HEAP_SCAVENGER_H_
