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 |