Index: runtime/vm/pages.cc |
=================================================================== |
--- runtime/vm/pages.cc (revision 34740) |
+++ runtime/vm/pages.cc (working copy) |
@@ -124,6 +124,9 @@ |
pages_tail_(NULL), |
large_pages_(NULL), |
max_capacity_in_words_(max_capacity_in_words), |
+ capacity_in_words_(0), |
+ used_in_words_(0), |
+ external_in_words_(0), |
sweeping_(false), |
page_space_controller_(FLAG_heap_growth_space_ratio, |
FLAG_heap_growth_rate, |
@@ -162,7 +165,7 @@ |
} |
} |
pages_tail_ = page; |
- usage_.capacity_in_words += kPageSizeInWords; |
+ capacity_in_words_ += kPageSizeInWords; |
page->set_object_end(page->memory_->end()); |
return page; |
} |
@@ -173,7 +176,7 @@ |
HeapPage* page = HeapPage::Allocate(page_size_in_words, type); |
page->set_next(large_pages_); |
large_pages_ = page; |
- usage_.capacity_in_words += page_size_in_words; |
+ capacity_in_words_ += page_size_in_words; |
// Only one object in this page. |
page->set_object_end(page->object_start() + size); |
return page; |
@@ -181,7 +184,7 @@ |
void PageSpace::FreePage(HeapPage* page, HeapPage* previous_page) { |
- usage_.capacity_in_words -= (page->memory_->size() >> kWordSizeLog2); |
+ capacity_in_words_ -= (page->memory_->size() >> kWordSizeLog2); |
// Remove the page from the list. |
if (previous_page != NULL) { |
previous_page->set_next(page->next()); |
@@ -197,7 +200,7 @@ |
void PageSpace::FreeLargePage(HeapPage* page, HeapPage* previous_page) { |
- usage_.capacity_in_words -= (page->memory_->size() >> kWordSizeLog2); |
+ capacity_in_words_ -= (page->memory_->size() >> kWordSizeLog2); |
// Remove the page from the list. |
if (previous_page != NULL) { |
previous_page->set_next(page->next()); |
@@ -224,28 +227,23 @@ |
ASSERT(size >= kObjectAlignment); |
ASSERT(Utils::IsAligned(size, kObjectAlignment)); |
uword result = 0; |
- SpaceUsage after_allocation = usage_; |
- after_allocation.used_in_words += size >> kWordSizeLog2; |
if (size < kAllocatablePageSize) { |
const bool is_protected = (type == HeapPage::kExecutable) |
&& FLAG_write_protect_code; |
result = freelist_[type].TryAllocate(size, is_protected); |
- if (result == 0) { |
- // Can we grow by one page? |
- after_allocation.capacity_in_words += kPageSizeInWords; |
- if ((!page_space_controller_.NeedsGarbageCollection(after_allocation) || |
- growth_policy == kForceGrowth) && |
- CanIncreaseCapacityInWords(kPageSizeInWords)) { |
- HeapPage* page = AllocatePage(type); |
- ASSERT(page != NULL); |
- // Start of the newly allocated page is the allocated object. |
- result = page->object_start(); |
- // Enqueue the remainder in the free list. |
- uword free_start = result + size; |
- intptr_t free_size = page->object_end() - free_start; |
- if (free_size > 0) { |
- freelist_[type].Free(free_start, free_size); |
- } |
+ if ((result == 0) && |
+ (page_space_controller_.CanGrowPageSpace(size) || |
+ growth_policy == kForceGrowth) && |
+ CanIncreaseCapacityInWords(kPageSizeInWords)) { |
+ HeapPage* page = AllocatePage(type); |
+ ASSERT(page != NULL); |
+ // Start of the newly allocated page is the allocated object. |
+ result = page->object_start(); |
+ // Enqueue the remainder in the free list. |
+ uword free_start = result + size; |
+ intptr_t free_size = page->object_end() - free_start; |
+ if (free_size > 0) { |
+ freelist_[type].Free(free_start, free_size); |
} |
} |
} else { |
@@ -255,8 +253,7 @@ |
// On overflow we fail to allocate. |
return 0; |
} |
- after_allocation.capacity_in_words += page_size_in_words; |
- if ((!page_space_controller_.NeedsGarbageCollection(after_allocation) || |
+ if ((page_space_controller_.CanGrowPageSpace(size) || |
growth_policy == kForceGrowth) && |
CanIncreaseCapacityInWords(page_size_in_words)) { |
HeapPage* page = AllocateLargePage(size, type); |
@@ -266,7 +263,7 @@ |
} |
} |
if (result != 0) { |
- usage_ = after_allocation; |
+ used_in_words_ += (size >> kWordSizeLog2); |
if (FLAG_compiler_stats && (type == HeapPage::kExecutable)) { |
CompilerStats::code_allocated += size; |
} |
@@ -278,14 +275,13 @@ |
void PageSpace::AllocateExternal(intptr_t size) { |
intptr_t size_in_words = size >> kWordSizeLog2; |
- usage_.external_in_words += size_in_words; |
- // TODO(koda): Control growth. |
+ external_in_words_ += size_in_words; |
} |
void PageSpace::FreeExternal(intptr_t size) { |
intptr_t size_in_words = size >> kWordSizeLog2; |
- usage_.external_in_words -= size_in_words; |
+ external_in_words_ -= size_in_words; |
} |
@@ -534,8 +530,7 @@ |
} |
// Save old value before GCMarker visits the weak persistent handles. |
- SpaceUsage usage_before = usage_; |
- usage_.used_in_words = 0; |
+ intptr_t external_before_in_words = external_in_words_; |
// Mark all reachable old-gen objects. |
bool collect_code = FLAG_collect_code && ShouldCollectCode(); |
@@ -552,6 +547,7 @@ |
int64_t mid2 = OS::GetCurrentTimeMicros(); |
GCSweeper sweeper(heap_); |
+ intptr_t used_in_words = 0; |
HeapPage* prev_page = NULL; |
HeapPage* page = pages_; |
@@ -561,7 +557,7 @@ |
if (page_in_use == 0) { |
FreePage(page, prev_page); |
} else { |
- usage_.used_in_words += (page_in_use >> kWordSizeLog2); |
+ used_in_words += (page_in_use >> kWordSizeLog2); |
prev_page = page; |
} |
// Advance to the next page. |
@@ -578,7 +574,7 @@ |
if (page_in_use == 0) { |
FreeLargePage(page, prev_page); |
} else { |
- usage_.used_in_words += (page_in_use >> kWordSizeLog2); |
+ used_in_words += (page_in_use >> kWordSizeLog2); |
prev_page = page; |
} |
// Advance to the next page. |
@@ -603,11 +599,17 @@ |
} |
} |
+ // Record data and print if requested. |
+ intptr_t used_before_in_words = used_in_words_; |
+ used_in_words_ = used_in_words; |
+ |
int64_t end = OS::GetCurrentTimeMicros(); |
// Record signals for growth control. Include size of external allocations. |
- page_space_controller_.EvaluateGarbageCollection(usage_before, usage_, |
- start, end); |
+ page_space_controller_.EvaluateGarbageCollection( |
+ used_before_in_words + external_before_in_words, |
+ used_in_words + external_in_words_, |
+ start, end); |
heap_->RecordTime(kMarkObjects, mid1 - start); |
heap_->RecordTime(kResetFreeLists, mid2 - mid1); |
@@ -649,35 +651,34 @@ |
PageSpaceController::~PageSpaceController() {} |
-bool PageSpaceController::NeedsGarbageCollection(SpaceUsage after) const { |
+bool PageSpaceController::CanGrowPageSpace(intptr_t size_in_bytes) { |
+ intptr_t size_in_words = size_in_bytes >> kWordSizeLog2; |
+ size_in_words = Utils::RoundUp(size_in_words, PageSpace::kPageSizeInWords); |
+ intptr_t size_in_pages = size_in_words / PageSpace::kPageSizeInWords; |
if (!is_enabled_) { |
- return false; |
+ return true; |
} |
if (heap_growth_ratio_ == 100) { |
+ return true; |
+ } |
+ if (grow_heap_ <= 0) { |
return false; |
} |
- intptr_t capacity_increase_in_words = |
- after.capacity_in_words - last_usage_.capacity_in_words; |
- ASSERT(capacity_increase_in_words >= 0); |
- intptr_t capacity_increase_in_pages = |
- Utils::RoundUp(capacity_increase_in_words, PageSpace::kPageSizeInWords); |
- return capacity_increase_in_pages >= grow_heap_; |
+ grow_heap_ -= size_in_pages; |
+ return true; |
} |
void PageSpaceController::EvaluateGarbageCollection( |
- SpaceUsage before, SpaceUsage after, int64_t start, int64_t end) { |
+ intptr_t used_before_in_words, intptr_t used_after_in_words, |
+ int64_t start, int64_t end) { |
// TODO(iposva): Reevaluate the growth policies. |
- intptr_t before_total_in_words = |
- before.used_in_words + before.external_in_words; |
- intptr_t after_total_in_words = |
- after.used_in_words + after.external_in_words; |
- ASSERT(before_total_in_words >= after_total_in_words); |
+ ASSERT(used_before_in_words >= used_after_in_words); |
ASSERT(end >= start); |
history_.AddGarbageCollectionTime(start, end); |
int collected_garbage_ratio = static_cast<int>( |
- (static_cast<double>(before_total_in_words - after_total_in_words) / |
- static_cast<double>(before_total_in_words)) |
+ (static_cast<double>(used_before_in_words - used_after_in_words) / |
+ static_cast<double>(used_before_in_words)) |
* 100.0); |
bool enough_free_space = |
(collected_garbage_ratio >= heap_growth_ratio_); |
@@ -691,9 +692,9 @@ |
grow_heap_ = 0; |
} else { |
intptr_t growth_target = static_cast<intptr_t>( |
- after_total_in_words / desired_utilization_); |
+ used_after_in_words / desired_utilization_); |
intptr_t growth_in_words = Utils::RoundUp( |
- growth_target - after_total_in_words, |
+ growth_target - used_after_in_words, |
PageSpace::kPageSizeInWords); |
int growth_in_pages = |
growth_in_words / PageSpace::kPageSizeInWords; |
@@ -704,7 +705,6 @@ |
heap->RecordData(PageSpace::kGCTimeFraction, |
garbage_collection_time_fraction); |
heap->RecordData(PageSpace::kAllowedGrowth, grow_heap_); |
- last_usage_ = after; |
} |