// 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 VM_HEAP_H_
#define VM_HEAP_H_

#include "platform/assert.h"
#include "vm/allocation.h"
#include "vm/flags.h"
#include "vm/globals.h"
#include "vm/pages.h"
#include "vm/scavenger.h"

namespace dart {

// Forward declarations.
class HeapTrace;
class Isolate;
class ObjectPointerVisitor;
class ObjectSet;
class VirtualMemory;

DECLARE_FLAG(bool, verbose_gc);
DECLARE_FLAG(bool, verify_before_gc);
DECLARE_FLAG(bool, verify_after_gc);
DECLARE_FLAG(bool, gc_at_alloc);

class Heap {
 public:
  enum Space {
    kNew,
    kOld,
    kCode,
  };

  enum ApiCallbacks {
    kIgnoreApiCallbacks,
    kInvokeApiCallbacks
  };

  enum GCReason {
    kNewSpace,
    kPromotionFailure,
    kOldSpace,
    kFull,
    kGCAtAlloc,
    kGCTestCase,
  };

  // Default allocation sizes in MB for the old gen and code heaps.
  static const intptr_t kHeapSizeInMB = 512;
  static const intptr_t kCodeHeapSizeInMB = 18;

  ~Heap();

  uword Allocate(intptr_t size, Space space) {
    ASSERT(!read_only_);
    switch (space) {
      case kNew:
        // Do not attempt to allocate very large objects in new space.
        if (!PageSpace::IsPageAllocatableSize(size)) {
          return AllocateOld(size, HeapPage::kData);
        }
        return AllocateNew(size);
      case kOld:
        return AllocateOld(size, HeapPage::kData);
      case kCode:
        return AllocateOld(size, HeapPage::kExecutable);
      default:
        UNREACHABLE();
    }
    return 0;
  }

  uword TryAllocate(
      intptr_t size,
      Space space,
      PageSpace::GrowthPolicy growth_policy = PageSpace::kControlGrowth) {
    ASSERT(!read_only_);
    switch (space) {
      case kNew:
        return new_space_->TryAllocate(size);
      case kOld:
        return old_space_->TryAllocate(size,
                                       HeapPage::kData,
                                       growth_policy);
      case kCode:
        return old_space_->TryAllocate(size,
                                       HeapPage::kExecutable,
                                       growth_policy);
      default:
        UNREACHABLE();
    }
    return 0;
  }

  // Heap contains the specified address.
  bool Contains(uword addr) const;
  bool NewContains(uword addr) const;
  bool OldContains(uword addr) const;
  bool CodeContains(uword addr) const;
  bool StubCodeContains(uword addr) const;

  // Visit all pointers.
  void IteratePointers(ObjectPointerVisitor* visitor);

  // Visit all pointers in the space.
  void IterateNewPointers(ObjectPointerVisitor* visitor);
  void IterateOldPointers(ObjectPointerVisitor* visitor);

  // Visit all objects.
  void IterateObjects(ObjectVisitor* visitor);

  // Visit all object in the space.
  void IterateNewObjects(ObjectVisitor* visitor);
  void IterateOldObjects(ObjectVisitor* visitor);

  // Find an object by visiting all pointers in the specified heap space,
  // the 'visitor' is used to determine if an object is found or not.
  // The 'visitor' function should be set up to return true if the
  // object is found, traversal through the heap space stops at that
  // point.
  // The 'visitor' function should return false if the object is not found,
  // traversal through the heap space continues.
  RawInstructions* FindObjectInCodeSpace(FindObjectVisitor* visitor);
  RawInstructions* FindObjectInStubCodeSpace(FindObjectVisitor* visitor);

  void CollectGarbage(Space space);
  void CollectGarbage(Space space, ApiCallbacks api_callbacks);
  void CollectAllGarbage();

  // Enables growth control on the page space heaps.  This should be
  // called before any user code is executed.
  void EnableGrowthControl();

  // Protect access to the heap.
  void WriteProtect(bool read_only);

  // Accessors for inlined allocation in generated code.
  uword TopAddress();
  uword EndAddress();
  static intptr_t new_space_offset() { return OFFSET_OF(Heap, new_space_); }

  // Initialize the heap and register it with the isolate.
  static void Init(Isolate* isolate);

  // Verify that all pointers in the heap point to the heap.
  bool Verify() const;

  // Accessor function to get the HeapTrace used for tracing.  There
  // should only ever be one of these per isolate
  HeapTrace* trace() const { return heap_trace_; }

  // Print heap sizes.
  void PrintSizes() const;

  // Return amount of memory used and capacity in a space.
  intptr_t Used(Space space) const;
  intptr_t Capacity(Space space) const;

  // Returns the [lowest, highest) addresses in the heap.
  void StartEndAddress(uword* start, uword* end) const;

  ObjectSet* CreateAllocatedObjectSet() const;

  // Generates a profile of the current and VM isolate heaps.
  void Profile(Dart_FileWriteCallback callback, void* stream) const;
  void ProfileToFile(const char* reason) const;

  static const char* GCReasonToString(GCReason gc_reason);

  // Associates a peer with an object.  If an object has a peer, it is
  // replaced.  A value of NULL disassociate an object from its peer.
  void SetPeer(RawObject* raw_obj, void* peer);

  // Retrieves the peer associated with an object.  Returns NULL if
  // there is no association.
  void* GetPeer(RawObject* raw_obj);

  // Returns the number of objects with a peer.
  int64_t PeerCount() const;

  // Stats collection.
  void RecordTime(int id, int64_t micros) {
    ASSERT((id >= 0) && (id < GCStats::kDataEntries));
    stats_.times_[id] = micros;
  }

  void RecordData(int id, intptr_t value) {
    ASSERT((id >= 0) && (id < GCStats::kDataEntries));
    stats_.data_[id] = value;
  }

  bool gc_in_progress() const { return gc_in_progress_; }

 private:
  class GCStats : public ValueObject {
   public:
    GCStats() {}
    intptr_t num_;
    Heap::Space space_;
    Heap::GCReason reason_;

    class Data : public ValueObject {
    public:
      Data() {}
      int64_t micros_;
      intptr_t new_used_;
      intptr_t new_capacity_;
      intptr_t old_used_;
      intptr_t old_capacity_;

      DISALLOW_COPY_AND_ASSIGN(Data);
    };

    enum {
      kDataEntries = 4
    };

    Data before_;
    Data after_;
    int64_t times_[kDataEntries];
    intptr_t data_[kDataEntries];

    DISALLOW_COPY_AND_ASSIGN(GCStats);
  };

  Heap();

  uword AllocateNew(intptr_t size);
  uword AllocateOld(intptr_t size, HeapPage::PageType type);

  // GC stats collection.
  void RecordBeforeGC(Space space, GCReason reason);
  void RecordAfterGC();
  void PrintStats();

  // The different spaces used for allocation.
  Scavenger* new_space_;
  PageSpace* old_space_;

  // GC stats collection.
  GCStats stats_;

  // The active heap trace.
  HeapTrace* heap_trace_;

  // This heap is in read-only mode: No allocation is allowed.
  bool read_only_;

  // GC on the heap is in progress.
  bool gc_in_progress_;

  friend class GCTestHelper;
  DISALLOW_COPY_AND_ASSIGN(Heap);
};


#if defined(DEBUG)
class NoGCScope : public StackResource {
 public:
  NoGCScope();
  ~NoGCScope();
 private:
  DISALLOW_COPY_AND_ASSIGN(NoGCScope);
};
#else  // defined(DEBUG)
class NoGCScope : public ValueObject {
 public:
  NoGCScope() {}
 private:
  DISALLOW_COPY_AND_ASSIGN(NoGCScope);
};
#endif  // defined(DEBUG)

}  // namespace dart

#endif  // VM_HEAP_H_
