Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/pages.h" | 5 #include "vm/pages.h" |
| 6 | 6 |
| 7 #include "platform/assert.h" | 7 #include "platform/assert.h" |
| 8 #include "vm/compiler_stats.h" | 8 #include "vm/compiler_stats.h" |
| 9 #include "vm/gc_marker.h" | 9 #include "vm/gc_marker.h" |
| 10 #include "vm/gc_sweeper.h" | 10 #include "vm/gc_sweeper.h" |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 105 if (executable_) { | 105 if (executable_) { |
| 106 prot = VirtualMemory::kReadWriteExecute; | 106 prot = VirtualMemory::kReadWriteExecute; |
| 107 } else { | 107 } else { |
| 108 prot = VirtualMemory::kReadWrite; | 108 prot = VirtualMemory::kReadWrite; |
| 109 } | 109 } |
| 110 } | 110 } |
| 111 memory_->Protect(prot); | 111 memory_->Protect(prot); |
| 112 } | 112 } |
| 113 | 113 |
| 114 | 114 |
| 115 PageSpace::PageSpace(Heap* heap, intptr_t max_capacity) | 115 PageSpace::PageSpace(Heap* heap, intptr_t max_capacity_in_words) |
| 116 : freelist_(), | 116 : freelist_(), |
| 117 heap_(heap), | 117 heap_(heap), |
| 118 pages_(NULL), | 118 pages_(NULL), |
| 119 pages_tail_(NULL), | 119 pages_tail_(NULL), |
| 120 large_pages_(NULL), | 120 large_pages_(NULL), |
| 121 max_capacity_(max_capacity), | 121 max_capacity_in_words_(max_capacity_in_words), |
| 122 capacity_(0), | 122 capacity_in_words_(0), |
| 123 in_use_(0), | 123 used_in_words_(0), |
| 124 sweeping_(false), | 124 sweeping_(false), |
| 125 page_space_controller_(FLAG_heap_growth_space_ratio, | 125 page_space_controller_(FLAG_heap_growth_space_ratio, |
| 126 FLAG_heap_growth_rate, | 126 FLAG_heap_growth_rate, |
| 127 FLAG_heap_growth_time_ratio) { | 127 FLAG_heap_growth_time_ratio) { |
| 128 } | 128 } |
| 129 | 129 |
| 130 | 130 |
| 131 PageSpace::~PageSpace() { | 131 PageSpace::~PageSpace() { |
| 132 FreePages(pages_); | 132 FreePages(pages_); |
| 133 FreePages(large_pages_); | 133 FreePages(large_pages_); |
| 134 } | 134 } |
| 135 | 135 |
| 136 | 136 |
| 137 intptr_t PageSpace::LargePageSizeFor(intptr_t size) { | 137 intptr_t PageSpace::LargePageSizeFor(intptr_t size) { |
| 138 intptr_t page_size = Utils::RoundUp(size + HeapPage::ObjectStartOffset(), | 138 intptr_t page_size = Utils::RoundUp(size + HeapPage::ObjectStartOffset(), |
| 139 VirtualMemory::PageSize()); | 139 VirtualMemory::PageSize()); |
| 140 return page_size; | 140 return page_size; |
| 141 } | 141 } |
| 142 | 142 |
| 143 | 143 |
| 144 HeapPage* PageSpace::AllocatePage(HeapPage::PageType type) { | 144 HeapPage* PageSpace::AllocatePage(HeapPage::PageType type) { |
| 145 HeapPage* page = HeapPage::Allocate(kPageSize, type); | 145 HeapPage* page = HeapPage::Allocate(kPageSize, type); |
| 146 if (pages_ == NULL) { | 146 if (pages_ == NULL) { |
| 147 pages_ = page; | 147 pages_ = page; |
| 148 } else { | 148 } else { |
| 149 pages_tail_->set_next(page); | 149 pages_tail_->set_next(page); |
| 150 } | 150 } |
| 151 pages_tail_ = page; | 151 pages_tail_ = page; |
| 152 capacity_ += kPageSize; | 152 capacity_in_words_ += (kPageSize >> kWordSizeLog2); |
|
siva
2013/11/15 22:06:22
Why not have kPageSizeInWords ?
| |
| 153 page->set_object_end(page->memory_->end()); | 153 page->set_object_end(page->memory_->end()); |
| 154 return page; | 154 return page; |
| 155 } | 155 } |
| 156 | 156 |
| 157 | 157 |
| 158 HeapPage* PageSpace::AllocateLargePage(intptr_t size, HeapPage::PageType type) { | 158 HeapPage* PageSpace::AllocateLargePage(intptr_t size, HeapPage::PageType type) { |
|
siva
2013/11/15 22:06:22
Why is this size not in words? It is confusing tha
Ivan Posva
2013/11/16 00:16:57
HeapPage has not been updated yet.
| |
| 159 intptr_t page_size = LargePageSizeFor(size); | 159 intptr_t page_size = LargePageSizeFor(size); |
| 160 HeapPage* page = HeapPage::Allocate(page_size, type); | 160 HeapPage* page = HeapPage::Allocate(page_size, type); |
| 161 page->set_next(large_pages_); | 161 page->set_next(large_pages_); |
| 162 large_pages_ = page; | 162 large_pages_ = page; |
| 163 capacity_ += page_size; | 163 capacity_in_words_ += (page_size >> kWordSizeLog2); |
| 164 // Only one object in this page. | 164 // Only one object in this page. |
| 165 page->set_object_end(page->object_start() + size); | 165 page->set_object_end(page->object_start() + size); |
| 166 return page; | 166 return page; |
| 167 } | 167 } |
| 168 | 168 |
| 169 | 169 |
| 170 void PageSpace::FreePage(HeapPage* page, HeapPage* previous_page) { | 170 void PageSpace::FreePage(HeapPage* page, HeapPage* previous_page) { |
| 171 capacity_ -= page->memory_->size(); | 171 capacity_in_words_ -= (page->memory_->size() >> kWordSizeLog2); |
| 172 // Remove the page from the list. | 172 // Remove the page from the list. |
| 173 if (previous_page != NULL) { | 173 if (previous_page != NULL) { |
| 174 previous_page->set_next(page->next()); | 174 previous_page->set_next(page->next()); |
| 175 } else { | 175 } else { |
| 176 pages_ = page->next(); | 176 pages_ = page->next(); |
| 177 } | 177 } |
| 178 if (page == pages_tail_) { | 178 if (page == pages_tail_) { |
| 179 pages_tail_ = previous_page; | 179 pages_tail_ = previous_page; |
| 180 } | 180 } |
| 181 // TODO(iposva): Consider adding to a pool of empty pages. | 181 // TODO(iposva): Consider adding to a pool of empty pages. |
| 182 page->Deallocate(); | 182 page->Deallocate(); |
| 183 } | 183 } |
| 184 | 184 |
| 185 | 185 |
| 186 void PageSpace::FreeLargePage(HeapPage* page, HeapPage* previous_page) { | 186 void PageSpace::FreeLargePage(HeapPage* page, HeapPage* previous_page) { |
| 187 capacity_ -= page->memory_->size(); | 187 capacity_in_words_ -= (page->memory_->size() >> kWordSizeLog2); |
| 188 // Remove the page from the list. | 188 // Remove the page from the list. |
| 189 if (previous_page != NULL) { | 189 if (previous_page != NULL) { |
| 190 previous_page->set_next(page->next()); | 190 previous_page->set_next(page->next()); |
| 191 } else { | 191 } else { |
| 192 large_pages_ = page->next(); | 192 large_pages_ = page->next(); |
| 193 } | 193 } |
| 194 page->Deallocate(); | 194 page->Deallocate(); |
| 195 } | 195 } |
| 196 | 196 |
| 197 | 197 |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 209 HeapPage::PageType type, | 209 HeapPage::PageType type, |
| 210 GrowthPolicy growth_policy) { | 210 GrowthPolicy growth_policy) { |
| 211 ASSERT(size >= kObjectAlignment); | 211 ASSERT(size >= kObjectAlignment); |
| 212 ASSERT(Utils::IsAligned(size, kObjectAlignment)); | 212 ASSERT(Utils::IsAligned(size, kObjectAlignment)); |
| 213 uword result = 0; | 213 uword result = 0; |
| 214 if (size < kAllocatablePageSize) { | 214 if (size < kAllocatablePageSize) { |
| 215 result = freelist_[type].TryAllocate(size); | 215 result = freelist_[type].TryAllocate(size); |
| 216 if ((result == 0) && | 216 if ((result == 0) && |
| 217 (page_space_controller_.CanGrowPageSpace(size) || | 217 (page_space_controller_.CanGrowPageSpace(size) || |
| 218 growth_policy == kForceGrowth) && | 218 growth_policy == kForceGrowth) && |
| 219 CanIncreaseCapacity(kPageSize)) { | 219 CanIncreaseCapacityInWords(kPageSize >> kWordSizeLog2)) { |
| 220 HeapPage* page = AllocatePage(type); | 220 HeapPage* page = AllocatePage(type); |
| 221 ASSERT(page != NULL); | 221 ASSERT(page != NULL); |
| 222 // Start of the newly allocated page is the allocated object. | 222 // Start of the newly allocated page is the allocated object. |
| 223 result = page->object_start(); | 223 result = page->object_start(); |
| 224 // Enqueue the remainder in the free list. | 224 // Enqueue the remainder in the free list. |
| 225 uword free_start = result + size; | 225 uword free_start = result + size; |
| 226 intptr_t free_size = page->object_end() - free_start; | 226 intptr_t free_size = page->object_end() - free_start; |
| 227 if (free_size > 0) { | 227 if (free_size > 0) { |
| 228 freelist_[type].Free(free_start, free_size); | 228 freelist_[type].Free(free_start, free_size); |
| 229 } | 229 } |
| 230 } | 230 } |
| 231 } else { | 231 } else { |
| 232 // Large page allocation. | 232 // Large page allocation. |
| 233 intptr_t page_size = LargePageSizeFor(size); | 233 intptr_t page_size = LargePageSizeFor(size); |
| 234 if (page_size < size) { | 234 if (page_size < size) { |
| 235 // On overflow we fail to allocate. | 235 // On overflow we fail to allocate. |
| 236 return 0; | 236 return 0; |
| 237 } | 237 } |
| 238 if ((page_space_controller_.CanGrowPageSpace(size) || | 238 if ((page_space_controller_.CanGrowPageSpace(size) || |
| 239 growth_policy == kForceGrowth) && | 239 growth_policy == kForceGrowth) && |
| 240 CanIncreaseCapacity(page_size)) { | 240 CanIncreaseCapacityInWords(page_size >> kWordSizeLog2)) { |
| 241 HeapPage* page = AllocateLargePage(size, type); | 241 HeapPage* page = AllocateLargePage(size, type); |
| 242 if (page != NULL) { | 242 if (page != NULL) { |
| 243 result = page->object_start(); | 243 result = page->object_start(); |
| 244 } | 244 } |
| 245 } | 245 } |
| 246 } | 246 } |
| 247 if (result != 0) { | 247 if (result != 0) { |
| 248 in_use_ += size; | 248 used_in_words_ += (size >> kWordSizeLog2); |
| 249 if (FLAG_compiler_stats && (type == HeapPage::kExecutable)) { | 249 if (FLAG_compiler_stats && (type == HeapPage::kExecutable)) { |
| 250 CompilerStats::code_allocated += size; | 250 CompilerStats::code_allocated += size; |
| 251 } | 251 } |
| 252 } | 252 } |
| 253 ASSERT((result & kObjectAlignmentMask) == kOldObjectAlignmentOffset); | 253 ASSERT((result & kObjectAlignmentMask) == kOldObjectAlignmentOffset); |
| 254 return result; | 254 return result; |
| 255 } | 255 } |
| 256 | 256 |
| 257 | 257 |
| 258 bool PageSpace::Contains(uword addr) const { | 258 bool PageSpace::Contains(uword addr) const { |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 475 int64_t mid1 = OS::GetCurrentTimeMicros(); | 475 int64_t mid1 = OS::GetCurrentTimeMicros(); |
| 476 | 476 |
| 477 // Reset the bump allocation page to unused. | 477 // Reset the bump allocation page to unused. |
| 478 // Reset the freelists and setup sweeping. | 478 // Reset the freelists and setup sweeping. |
| 479 freelist_[HeapPage::kData].Reset(); | 479 freelist_[HeapPage::kData].Reset(); |
| 480 freelist_[HeapPage::kExecutable].Reset(); | 480 freelist_[HeapPage::kExecutable].Reset(); |
| 481 | 481 |
| 482 int64_t mid2 = OS::GetCurrentTimeMicros(); | 482 int64_t mid2 = OS::GetCurrentTimeMicros(); |
| 483 | 483 |
| 484 GCSweeper sweeper(heap_); | 484 GCSweeper sweeper(heap_); |
| 485 intptr_t in_use = 0; | 485 intptr_t used_in_words = 0; |
| 486 | 486 |
| 487 HeapPage* prev_page = NULL; | 487 HeapPage* prev_page = NULL; |
| 488 HeapPage* page = pages_; | 488 HeapPage* page = pages_; |
| 489 while (page != NULL) { | 489 while (page != NULL) { |
| 490 HeapPage* next_page = page->next(); | 490 HeapPage* next_page = page->next(); |
| 491 intptr_t page_in_use = sweeper.SweepPage(page, &freelist_[page->type()]); | 491 intptr_t page_in_use = sweeper.SweepPage(page, &freelist_[page->type()]); |
| 492 if (page_in_use == 0) { | 492 if (page_in_use == 0) { |
| 493 FreePage(page, prev_page); | 493 FreePage(page, prev_page); |
| 494 } else { | 494 } else { |
| 495 in_use += page_in_use; | 495 used_in_words += (page_in_use >> kWordSizeLog2); |
| 496 prev_page = page; | 496 prev_page = page; |
| 497 } | 497 } |
| 498 // Advance to the next page. | 498 // Advance to the next page. |
| 499 page = next_page; | 499 page = next_page; |
| 500 } | 500 } |
| 501 | 501 |
| 502 int64_t mid3 = OS::GetCurrentTimeMicros(); | 502 int64_t mid3 = OS::GetCurrentTimeMicros(); |
| 503 | 503 |
| 504 prev_page = NULL; | 504 prev_page = NULL; |
| 505 page = large_pages_; | 505 page = large_pages_; |
| 506 while (page != NULL) { | 506 while (page != NULL) { |
| 507 intptr_t page_in_use = sweeper.SweepLargePage(page); | 507 intptr_t page_in_use = sweeper.SweepLargePage(page); |
| 508 HeapPage* next_page = page->next(); | 508 HeapPage* next_page = page->next(); |
| 509 if (page_in_use == 0) { | 509 if (page_in_use == 0) { |
| 510 FreeLargePage(page, prev_page); | 510 FreeLargePage(page, prev_page); |
| 511 } else { | 511 } else { |
| 512 in_use += page_in_use; | 512 used_in_words += (page_in_use >> kWordSizeLog2); |
| 513 prev_page = page; | 513 prev_page = page; |
| 514 } | 514 } |
| 515 // Advance to the next page. | 515 // Advance to the next page. |
| 516 page = next_page; | 516 page = next_page; |
| 517 } | 517 } |
| 518 | 518 |
| 519 // Record data and print if requested. | 519 // Record data and print if requested. |
| 520 intptr_t in_use_before = in_use_; | 520 intptr_t used_before_in_words = used_in_words_; |
| 521 in_use_ = in_use; | 521 used_in_words_ = used_in_words; |
| 522 | 522 |
| 523 int64_t end = OS::GetCurrentTimeMicros(); | 523 int64_t end = OS::GetCurrentTimeMicros(); |
| 524 | 524 |
| 525 // Record signals for growth control. | 525 // Record signals for growth control. |
| 526 page_space_controller_.EvaluateGarbageCollection(in_use_before, in_use, | 526 page_space_controller_.EvaluateGarbageCollection(used_before_in_words, |
| 527 used_in_words, | |
| 527 start, end); | 528 start, end); |
| 528 | 529 |
| 529 heap_->RecordTime(kMarkObjects, mid1 - start); | 530 heap_->RecordTime(kMarkObjects, mid1 - start); |
| 530 heap_->RecordTime(kResetFreeLists, mid2 - mid1); | 531 heap_->RecordTime(kResetFreeLists, mid2 - mid1); |
| 531 heap_->RecordTime(kSweepPages, mid3 - mid2); | 532 heap_->RecordTime(kSweepPages, mid3 - mid2); |
| 532 heap_->RecordTime(kSweepLargePages, end - mid3); | 533 heap_->RecordTime(kSweepLargePages, end - mid3); |
| 533 | 534 |
| 534 if (FLAG_print_free_list_after_gc) { | 535 if (FLAG_print_free_list_after_gc) { |
| 535 OS::Print("Data Freelist (after GC):\n"); | 536 OS::Print("Data Freelist (after GC):\n"); |
| 536 freelist_[HeapPage::kData].Print(); | 537 freelist_[HeapPage::kData].Print(); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 577 } | 578 } |
| 578 if (grow_heap_ <= 0) { | 579 if (grow_heap_ <= 0) { |
| 579 return false; | 580 return false; |
| 580 } | 581 } |
| 581 grow_heap_ -= size_in_pages; | 582 grow_heap_ -= size_in_pages; |
| 582 return true; | 583 return true; |
| 583 } | 584 } |
| 584 | 585 |
| 585 | 586 |
| 586 void PageSpaceController::EvaluateGarbageCollection( | 587 void PageSpaceController::EvaluateGarbageCollection( |
| 587 intptr_t in_use_before, intptr_t in_use_after, int64_t start, int64_t end) { | 588 intptr_t used_before_in_words, intptr_t used_after_in_words, |
| 588 ASSERT(in_use_before >= in_use_after); | 589 int64_t start, int64_t end) { |
| 590 // TODO(iposva): Reevaluate the growth policies. | |
| 591 ASSERT(used_before_in_words >= used_after_in_words); | |
| 589 ASSERT(end >= start); | 592 ASSERT(end >= start); |
| 590 history_.AddGarbageCollectionTime(start, end); | 593 history_.AddGarbageCollectionTime(start, end); |
| 591 int collected_garbage_ratio = | 594 int collected_garbage_ratio = static_cast<int>( |
| 592 static_cast<int>((static_cast<double>(in_use_before - in_use_after) / | 595 (static_cast<double>(used_before_in_words - used_after_in_words) / |
| 593 static_cast<double>(in_use_before)) | 596 static_cast<double>(used_before_in_words)) |
| 594 * 100.0); | 597 * 100.0); |
| 595 bool enough_free_space = | 598 bool enough_free_space = |
| 596 (collected_garbage_ratio >= heap_growth_ratio_); | 599 (collected_garbage_ratio >= heap_growth_ratio_); |
| 597 int garbage_collection_time_fraction = | 600 int garbage_collection_time_fraction = |
| 598 history_.GarbageCollectionTimeFraction(); | 601 history_.GarbageCollectionTimeFraction(); |
| 599 bool enough_free_time = | 602 bool enough_free_time = |
| 600 (garbage_collection_time_fraction <= garbage_collection_time_ratio_); | 603 (garbage_collection_time_fraction <= garbage_collection_time_ratio_); |
| 601 | 604 |
| 602 Heap* heap = Isolate::Current()->heap(); | 605 Heap* heap = Isolate::Current()->heap(); |
| 603 if (enough_free_space && enough_free_time) { | 606 if (enough_free_space && enough_free_time) { |
| 604 grow_heap_ = 0; | 607 grow_heap_ = 0; |
| 605 } else { | 608 } else { |
| 606 intptr_t growth_target = static_cast<intptr_t>(in_use_after / | 609 intptr_t growth_target = static_cast<intptr_t>( |
| 607 desired_utilization_); | 610 used_after_in_words / desired_utilization_); |
| 608 intptr_t growth_in_bytes = Utils::RoundUp(growth_target - in_use_after, | 611 intptr_t growth_in_words = Utils::RoundUp( |
| 609 PageSpace::kPageSize); | 612 growth_target - used_after_in_words, |
| 610 int growth_in_pages = growth_in_bytes / PageSpace::kPageSize; | 613 PageSpace::kPageSize >> kWordSizeLog2); |
| 614 int growth_in_pages = | |
| 615 growth_in_words / (PageSpace::kPageSize >> kWordSizeLog2); | |
| 611 grow_heap_ = Utils::Maximum(growth_in_pages, heap_growth_rate_); | 616 grow_heap_ = Utils::Maximum(growth_in_pages, heap_growth_rate_); |
| 612 heap->RecordData(PageSpace::kPageGrowth, growth_in_pages); | 617 heap->RecordData(PageSpace::kPageGrowth, growth_in_pages); |
| 613 } | 618 } |
| 614 heap->RecordData(PageSpace::kGarbageRatio, collected_garbage_ratio); | 619 heap->RecordData(PageSpace::kGarbageRatio, collected_garbage_ratio); |
| 615 heap->RecordData(PageSpace::kGCTimeFraction, | 620 heap->RecordData(PageSpace::kGCTimeFraction, |
| 616 garbage_collection_time_fraction); | 621 garbage_collection_time_fraction); |
| 617 heap->RecordData(PageSpace::kAllowedGrowth, grow_heap_); | 622 heap->RecordData(PageSpace::kAllowedGrowth, grow_heap_); |
| 618 } | 623 } |
| 619 | 624 |
| 620 | 625 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 655 return 0; | 660 return 0; |
| 656 } else { | 661 } else { |
| 657 ASSERT(total_time >= gc_time); | 662 ASSERT(total_time >= gc_time); |
| 658 int result= static_cast<int>((static_cast<double>(gc_time) / | 663 int result= static_cast<int>((static_cast<double>(gc_time) / |
| 659 static_cast<double>(total_time)) * 100); | 664 static_cast<double>(total_time)) * 100); |
| 660 return result; | 665 return result; |
| 661 } | 666 } |
| 662 } | 667 } |
| 663 | 668 |
| 664 } // namespace dart | 669 } // namespace dart |
| OLD | NEW |