| 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;
|
| }
|
|
|
|
|
|
|