2011-10-05 05:20:07 +00:00
|
|
|
// Copyright (c) 2011, 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_PAGES_H_
|
|
|
|
#define VM_PAGES_H_
|
|
|
|
|
2012-09-18 21:15:46 +00:00
|
|
|
#include <map>
|
|
|
|
|
2011-12-15 22:37:35 +00:00
|
|
|
#include "vm/freelist.h"
|
2011-10-05 05:20:07 +00:00
|
|
|
#include "vm/globals.h"
|
|
|
|
#include "vm/virtual_memory.h"
|
|
|
|
|
|
|
|
namespace dart {
|
|
|
|
|
|
|
|
// Forward declarations.
|
|
|
|
class Heap;
|
|
|
|
class ObjectPointerVisitor;
|
|
|
|
|
|
|
|
// An aligned page containing old generation objects. Alignment is used to be
|
|
|
|
// able to get to a HeapPage header quickly based on a pointer to an object.
|
|
|
|
class HeapPage {
|
|
|
|
public:
|
2012-10-25 23:46:01 +00:00
|
|
|
enum PageType {
|
|
|
|
kData = 0,
|
|
|
|
kExecutable,
|
|
|
|
kNumPageTypes
|
|
|
|
};
|
|
|
|
|
2011-10-05 05:20:07 +00:00
|
|
|
HeapPage* next() const { return next_; }
|
|
|
|
void set_next(HeapPage* next) { next_ = next; }
|
|
|
|
|
|
|
|
bool Contains(uword addr) {
|
|
|
|
return memory_->Contains(addr);
|
|
|
|
}
|
|
|
|
|
2012-10-18 17:40:12 +00:00
|
|
|
uword object_start() const {
|
2012-10-25 23:46:01 +00:00
|
|
|
return (reinterpret_cast<uword>(this) +
|
|
|
|
Utils::RoundUp(sizeof(HeapPage), kObjectAlignment));
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
2012-10-18 17:40:12 +00:00
|
|
|
uword object_end() const {
|
|
|
|
return object_end_;
|
|
|
|
}
|
2011-10-05 05:20:07 +00:00
|
|
|
|
|
|
|
void set_used(uword used) { used_ = used; }
|
|
|
|
uword used() const { return used_; }
|
|
|
|
void AddUsed(uword size) {
|
|
|
|
used_ += size;
|
|
|
|
}
|
|
|
|
|
2012-10-25 23:46:01 +00:00
|
|
|
PageType type() const {
|
|
|
|
return executable_ ? kExecutable : kData;
|
|
|
|
}
|
|
|
|
|
2012-06-14 00:08:07 +00:00
|
|
|
void VisitObjects(ObjectVisitor* visitor) const;
|
2011-10-05 05:20:07 +00:00
|
|
|
void VisitObjectPointers(ObjectPointerVisitor* visitor) const;
|
|
|
|
|
2012-04-09 18:20:23 +00:00
|
|
|
RawObject* FindObject(FindObjectVisitor* visitor) const;
|
|
|
|
|
2012-07-27 18:07:59 +00:00
|
|
|
void WriteProtect(bool read_only);
|
|
|
|
|
2011-10-05 05:20:07 +00:00
|
|
|
private:
|
2012-10-18 17:40:12 +00:00
|
|
|
void set_object_end(uword val) {
|
|
|
|
ASSERT((val & kObjectAlignmentMask) == kOldObjectAlignmentOffset);
|
|
|
|
object_end_ = val;
|
|
|
|
}
|
|
|
|
|
2012-10-25 23:46:01 +00:00
|
|
|
static HeapPage* Initialize(VirtualMemory* memory, PageType type);
|
|
|
|
static HeapPage* Allocate(intptr_t size, PageType type);
|
2011-10-05 05:20:07 +00:00
|
|
|
|
|
|
|
// Deallocate the virtual memory backing this page. The page pointer to this
|
|
|
|
// page becomes immediately inaccessible.
|
|
|
|
void Deallocate();
|
|
|
|
|
|
|
|
VirtualMemory* memory_;
|
|
|
|
HeapPage* next_;
|
|
|
|
uword used_;
|
2012-10-18 17:40:12 +00:00
|
|
|
uword object_end_;
|
2012-10-25 23:46:01 +00:00
|
|
|
bool executable_;
|
2011-10-05 05:20:07 +00:00
|
|
|
|
|
|
|
friend class PageSpace;
|
|
|
|
|
|
|
|
DISALLOW_ALLOCATION();
|
|
|
|
DISALLOW_IMPLICIT_CONSTRUCTORS(HeapPage);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2012-05-31 02:49:56 +00:00
|
|
|
// The history holds the timing information of the last garbage collection
|
|
|
|
// runs.
|
|
|
|
class PageSpaceGarbageCollectionHistory {
|
|
|
|
public:
|
|
|
|
PageSpaceGarbageCollectionHistory();
|
|
|
|
~PageSpaceGarbageCollectionHistory() {}
|
|
|
|
|
2012-06-22 21:17:38 +00:00
|
|
|
void AddGarbageCollectionTime(int64_t start, int64_t end);
|
2012-05-31 02:49:56 +00:00
|
|
|
|
|
|
|
int GarbageCollectionTimeFraction();
|
|
|
|
|
|
|
|
private:
|
2012-06-22 21:17:38 +00:00
|
|
|
static const intptr_t kHistoryLength = 4;
|
|
|
|
int64_t start_[kHistoryLength];
|
|
|
|
int64_t end_[kHistoryLength];
|
|
|
|
intptr_t index_;
|
2012-05-31 02:49:56 +00:00
|
|
|
|
|
|
|
DISALLOW_ALLOCATION();
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(PageSpaceGarbageCollectionHistory);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// If GC is able to reclaim more than heap_growth_ratio (in percent) memory
|
|
|
|
// and if the relative GC time is below a given threshold,
|
|
|
|
// then the heap is not grown when the next GC decision is made.
|
|
|
|
// PageSpaceController controls the heap size.
|
|
|
|
class PageSpaceController {
|
|
|
|
public:
|
|
|
|
PageSpaceController(int heap_growth_ratio,
|
|
|
|
int heap_growth_rate,
|
|
|
|
int garbage_collection_time_ratio);
|
|
|
|
~PageSpaceController();
|
|
|
|
|
|
|
|
bool CanGrowPageSpace(intptr_t size_in_bytes);
|
|
|
|
|
|
|
|
// A garbage collection is considered as successful if more than
|
|
|
|
// heap_growth_ratio % of memory got deallocated by the garbage collector.
|
|
|
|
// In this case garbage collection will be performed next time. Otherwise
|
|
|
|
// the heap will grow.
|
2012-08-28 02:32:55 +00:00
|
|
|
void EvaluateGarbageCollection(intptr_t in_use_before, intptr_t in_use_after,
|
2012-05-31 02:49:56 +00:00
|
|
|
int64_t start, int64_t end);
|
|
|
|
|
|
|
|
void Enable() {
|
|
|
|
is_enabled_ = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
bool is_enabled_;
|
|
|
|
|
|
|
|
// Heap growth control variable.
|
|
|
|
uword grow_heap_;
|
|
|
|
|
|
|
|
// If the garbage collector was not able to free more than heap_growth_ratio_
|
|
|
|
// memory, then the heap is grown. Otherwise garbage collection is performed.
|
|
|
|
int heap_growth_ratio_;
|
|
|
|
|
2012-08-28 02:32:55 +00:00
|
|
|
// The desired percent of heap in-use after a garbage collection.
|
|
|
|
// Equivalent to \frac{100-heap_growth_ratio_}{100}.
|
|
|
|
double desired_utilization_;
|
|
|
|
|
2012-05-31 02:49:56 +00:00
|
|
|
// Number of pages we grow.
|
|
|
|
int heap_growth_rate_;
|
|
|
|
|
|
|
|
// If the relative GC time stays below garbage_collection_time_ratio_
|
|
|
|
// garbage collection can be performed.
|
|
|
|
int garbage_collection_time_ratio_;
|
|
|
|
|
|
|
|
PageSpaceGarbageCollectionHistory history_;
|
|
|
|
|
|
|
|
DISALLOW_IMPLICIT_CONSTRUCTORS(PageSpaceController);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2011-10-05 05:20:07 +00:00
|
|
|
class PageSpace {
|
|
|
|
public:
|
|
|
|
// TODO(iposva): Determine heap sizes and tune the page size accordingly.
|
|
|
|
static const intptr_t kPageSize = 256 * KB;
|
|
|
|
static const intptr_t kPageAlignment = kPageSize;
|
|
|
|
|
2012-06-07 22:29:09 +00:00
|
|
|
enum GrowthPolicy {
|
|
|
|
kControlGrowth,
|
|
|
|
kForceGrowth
|
|
|
|
};
|
|
|
|
|
2012-10-25 23:46:01 +00:00
|
|
|
PageSpace(Heap* heap, intptr_t max_capacity);
|
2011-10-05 05:20:07 +00:00
|
|
|
~PageSpace();
|
|
|
|
|
2012-10-25 23:46:01 +00:00
|
|
|
uword TryAllocate(intptr_t size,
|
|
|
|
HeapPage::PageType type = HeapPage::kData,
|
|
|
|
GrowthPolicy growth_policy = kControlGrowth);
|
2011-10-05 05:20:07 +00:00
|
|
|
|
|
|
|
intptr_t in_use() const { return in_use_; }
|
2012-05-23 03:29:00 +00:00
|
|
|
intptr_t capacity() const { return capacity_; }
|
|
|
|
|
2011-10-05 05:20:07 +00:00
|
|
|
bool Contains(uword addr) const;
|
2012-10-25 23:46:01 +00:00
|
|
|
bool Contains(uword addr, HeapPage::PageType type) const;
|
2011-10-05 05:20:07 +00:00
|
|
|
bool IsValidAddress(uword addr) const {
|
|
|
|
return Contains(addr);
|
|
|
|
}
|
2011-12-19 19:29:10 +00:00
|
|
|
static bool IsPageAllocatableSize(intptr_t size) {
|
2011-10-05 05:20:07 +00:00
|
|
|
return size <= kAllocatablePageSize;
|
|
|
|
}
|
|
|
|
|
2012-06-14 00:08:07 +00:00
|
|
|
void VisitObjects(ObjectVisitor* visitor) const;
|
2011-10-05 05:20:07 +00:00
|
|
|
void VisitObjectPointers(ObjectPointerVisitor* visitor) const;
|
|
|
|
|
2012-10-25 23:46:01 +00:00
|
|
|
RawObject* FindObject(FindObjectVisitor* visitor,
|
|
|
|
HeapPage::PageType type) const;
|
2012-04-09 18:20:23 +00:00
|
|
|
|
2011-12-01 02:11:40 +00:00
|
|
|
// Collect the garbage in the page space using mark-sweep.
|
2012-08-29 00:49:14 +00:00
|
|
|
void MarkSweep(bool invoke_api_callbacks, const char* gc_reason);
|
2011-12-01 02:11:40 +00:00
|
|
|
|
2011-12-15 22:37:35 +00:00
|
|
|
static HeapPage* PageFor(RawObject* raw_obj) {
|
|
|
|
return reinterpret_cast<HeapPage*>(
|
|
|
|
RawObject::ToAddr(raw_obj) & ~(kPageSize -1));
|
|
|
|
}
|
|
|
|
|
2012-07-10 22:07:40 +00:00
|
|
|
void StartEndAddress(uword* start, uword* end) const;
|
|
|
|
|
2012-05-31 02:49:56 +00:00
|
|
|
void EnableGrowthControl() {
|
|
|
|
page_space_controller_.Enable();
|
|
|
|
}
|
|
|
|
|
2012-07-27 18:07:59 +00:00
|
|
|
void WriteProtect(bool read_only);
|
|
|
|
|
2012-09-18 21:15:46 +00:00
|
|
|
typedef std::map<RawObject*, void*> PeerTable;
|
|
|
|
|
|
|
|
void SetPeer(RawObject* raw_obj, void* peer);
|
|
|
|
|
|
|
|
void* GetPeer(RawObject* raw_obj);
|
|
|
|
|
|
|
|
int64_t PeerCount() const;
|
|
|
|
|
|
|
|
PeerTable* GetPeerTable() { return &peer_table_; }
|
|
|
|
|
2011-10-05 05:20:07 +00:00
|
|
|
private:
|
|
|
|
static const intptr_t kAllocatablePageSize = kPageSize - sizeof(HeapPage);
|
|
|
|
|
2012-10-25 23:46:01 +00:00
|
|
|
HeapPage* AllocatePage(HeapPage::PageType type);
|
2012-04-25 13:37:51 +00:00
|
|
|
void FreePage(HeapPage* page, HeapPage* previous_page);
|
2012-10-25 23:46:01 +00:00
|
|
|
HeapPage* AllocateLargePage(intptr_t size, HeapPage::PageType type);
|
2011-12-15 22:37:35 +00:00
|
|
|
void FreeLargePage(HeapPage* page, HeapPage* previous_page);
|
2011-10-05 05:20:07 +00:00
|
|
|
void FreePages(HeapPage* pages);
|
|
|
|
|
2011-12-16 23:40:41 +00:00
|
|
|
static intptr_t LargePageSizeFor(intptr_t size);
|
2012-05-23 03:29:00 +00:00
|
|
|
|
2011-12-16 23:40:41 +00:00
|
|
|
bool CanIncreaseCapacity(intptr_t increase) {
|
2011-12-23 00:14:05 +00:00
|
|
|
ASSERT(capacity_ <= max_capacity_);
|
2011-12-16 23:40:41 +00:00
|
|
|
return increase <= (max_capacity_ - capacity_);
|
|
|
|
}
|
|
|
|
|
2012-10-25 23:46:01 +00:00
|
|
|
FreeList freelist_[HeapPage::kNumPageTypes];
|
2011-12-15 22:37:35 +00:00
|
|
|
|
2011-10-05 05:20:07 +00:00
|
|
|
Heap* heap_;
|
|
|
|
|
|
|
|
HeapPage* pages_;
|
2012-04-20 12:14:31 +00:00
|
|
|
HeapPage* pages_tail_;
|
2011-10-05 05:20:07 +00:00
|
|
|
HeapPage* large_pages_;
|
|
|
|
|
2012-09-18 21:15:46 +00:00
|
|
|
PeerTable peer_table_;
|
|
|
|
|
2011-10-05 05:20:07 +00:00
|
|
|
// Various sizes being tracked for this generation.
|
|
|
|
intptr_t max_capacity_;
|
|
|
|
intptr_t capacity_;
|
|
|
|
intptr_t in_use_;
|
|
|
|
|
2011-12-01 02:11:40 +00:00
|
|
|
// Old-gen GC cycle count.
|
|
|
|
int count_;
|
|
|
|
|
|
|
|
// Keep track whether a MarkSweep is currently running.
|
|
|
|
bool sweeping_;
|
|
|
|
|
2012-05-31 02:49:56 +00:00
|
|
|
PageSpaceController page_space_controller_;
|
|
|
|
|
2011-10-05 05:20:07 +00:00
|
|
|
DISALLOW_IMPLICIT_CONSTRUCTORS(PageSpace);
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace dart
|
|
|
|
|
|
|
|
#endif // VM_PAGES_H_
|