Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(446)

Side by Side Diff: runtime/vm/pages.cc

Issue 511963007: Pretenure some strings into bump-allocated block (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« runtime/vm/freelist.cc ('K') | « runtime/vm/pages.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 17 matching lines...) Expand all
28 DEFINE_FLAG(bool, collect_code, true, 28 DEFINE_FLAG(bool, collect_code, true,
29 "Attempt to GC infrequently used code."); 29 "Attempt to GC infrequently used code.");
30 DEFINE_FLAG(int, code_collection_interval_in_us, 30000000, 30 DEFINE_FLAG(int, code_collection_interval_in_us, 30000000,
31 "Time between attempts to collect unused code."); 31 "Time between attempts to collect unused code.");
32 DEFINE_FLAG(bool, log_code_drop, false, 32 DEFINE_FLAG(bool, log_code_drop, false,
33 "Emit a log message when pointers to unused code are dropped."); 33 "Emit a log message when pointers to unused code are dropped.");
34 DEFINE_FLAG(bool, always_drop_code, false, 34 DEFINE_FLAG(bool, always_drop_code, false,
35 "Always try to drop code if the function's usage counter is >= 0"); 35 "Always try to drop code if the function's usage counter is >= 0");
36 DEFINE_FLAG(bool, concurrent_sweep, false, 36 DEFINE_FLAG(bool, concurrent_sweep, false,
37 "Concurrent sweep for old generation."); 37 "Concurrent sweep for old generation.");
38 DEFINE_FLAG(bool, log_growth, false, "Log PageSpace growth policy decisions.");
38 39
39 HeapPage* HeapPage::Initialize(VirtualMemory* memory, PageType type) { 40 HeapPage* HeapPage::Initialize(VirtualMemory* memory, PageType type) {
40 ASSERT(memory->size() > VirtualMemory::PageSize()); 41 ASSERT(memory->size() > VirtualMemory::PageSize());
41 bool is_executable = (type == kExecutable); 42 bool is_executable = (type == kExecutable);
42 memory->Commit(is_executable); 43 memory->Commit(is_executable);
43 44
44 HeapPage* result = reinterpret_cast<HeapPage*>(memory->address()); 45 HeapPage* result = reinterpret_cast<HeapPage*>(memory->address());
45 result->memory_ = memory; 46 result->memory_ = memory;
46 result->next_ = NULL; 47 result->next_ = NULL;
47 result->executable_ = is_executable; 48 result->executable_ = is_executable;
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
122 123
123 PageSpace::PageSpace(Heap* heap, intptr_t max_capacity_in_words) 124 PageSpace::PageSpace(Heap* heap, intptr_t max_capacity_in_words)
124 : freelist_(), 125 : freelist_(),
125 heap_(heap), 126 heap_(heap),
126 pages_lock_(new Mutex()), 127 pages_lock_(new Mutex()),
127 pages_(NULL), 128 pages_(NULL),
128 pages_tail_(NULL), 129 pages_tail_(NULL),
129 exec_pages_(NULL), 130 exec_pages_(NULL),
130 exec_pages_tail_(NULL), 131 exec_pages_tail_(NULL),
131 large_pages_(NULL), 132 large_pages_(NULL),
133 bump_top_(0),
134 bump_end_(0),
132 max_capacity_in_words_(max_capacity_in_words), 135 max_capacity_in_words_(max_capacity_in_words),
133 tasks_lock_(new Monitor()), 136 tasks_lock_(new Monitor()),
134 tasks_(0), 137 tasks_(0),
135 page_space_controller_(heap, 138 page_space_controller_(heap,
136 FLAG_heap_growth_space_ratio, 139 FLAG_heap_growth_space_ratio,
137 FLAG_heap_growth_rate, 140 FLAG_heap_growth_rate,
138 FLAG_heap_growth_time_ratio), 141 FLAG_heap_growth_time_ratio),
139 gc_time_micros_(0), 142 gc_time_micros_(0),
140 collections_(0) { 143 collections_(0) {
141 } 144 }
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 void PageSpace::FreePages(HeapPage* pages) { 277 void PageSpace::FreePages(HeapPage* pages) {
275 HeapPage* page = pages; 278 HeapPage* page = pages;
276 while (page != NULL) { 279 while (page != NULL) {
277 HeapPage* next = page->next(); 280 HeapPage* next = page->next();
278 page->Deallocate(); 281 page->Deallocate();
279 page = next; 282 page = next;
280 } 283 }
281 } 284 }
282 285
283 286
287 uword PageSpace::TryAllocateInNewPage(intptr_t size,
Ivan Posva 2014/08/29 00:07:12 TryAllocateInNewPage is a confusing name as it mak
koda 2014/08/29 00:52:20 Done.
288 HeapPage::PageType type,
289 GrowthPolicy growth_policy,
290 bool is_locked) {
291 ASSERT(size < kAllocatablePageSize);
292 uword result = 0;
293 SpaceUsage after_allocation = usage_;
294 after_allocation.used_in_words += size >> kWordSizeLog2;
295 // Can we grow by one page?
296 after_allocation.capacity_in_words += kPageSizeInWords;
297 if ((growth_policy == kForceGrowth ||
298 !page_space_controller_.NeedsGarbageCollection(after_allocation)) &&
299 CanIncreaseCapacityInWords(kPageSizeInWords)) {
300 HeapPage* page = AllocatePage(type);
301 ASSERT(page != NULL);
302 // Start of the newly allocated page is the allocated object.
303 result = page->object_start();
304 usage_ = after_allocation;
305 // Enqueue the remainder in the free list.
306 uword free_start = result + size;
307 intptr_t free_size = page->object_end() - free_start;
308 if (free_size > 0) {
309 if (is_locked) {
310 freelist_[type].FreeLocked(free_start, free_size);
311 } else {
312 freelist_[type].Free(free_start, free_size);
313 }
314 }
315 }
316 return result;
317 }
318
319
284 uword PageSpace::TryAllocateInternal(intptr_t size, 320 uword PageSpace::TryAllocateInternal(intptr_t size,
285 HeapPage::PageType type, 321 HeapPage::PageType type,
286 GrowthPolicy growth_policy, 322 GrowthPolicy growth_policy,
287 bool is_protected, 323 bool is_protected,
288 bool is_locked) { 324 bool is_locked) {
289 ASSERT(size >= kObjectAlignment); 325 ASSERT(size >= kObjectAlignment);
290 ASSERT(Utils::IsAligned(size, kObjectAlignment)); 326 ASSERT(Utils::IsAligned(size, kObjectAlignment));
291 uword result = 0; 327 uword result = 0;
292 SpaceUsage after_allocation = usage_;
293 after_allocation.used_in_words += size >> kWordSizeLog2;
294 if (size < kAllocatablePageSize) { 328 if (size < kAllocatablePageSize) {
295 if (is_locked) { 329 if (is_locked) {
296 result = freelist_[type].TryAllocateLocked(size, is_protected); 330 result = freelist_[type].TryAllocateLocked(size, is_protected);
297 } else { 331 } else {
298 result = freelist_[type].TryAllocate(size, is_protected); 332 result = freelist_[type].TryAllocate(size, is_protected);
299 } 333 }
300 if (result == 0) { 334 if (result == 0) {
301 // Can we grow by one page? 335 result = TryAllocateInNewPage(size, type, growth_policy, is_locked);
302 after_allocation.capacity_in_words += kPageSizeInWords;
303 if ((!page_space_controller_.NeedsGarbageCollection(after_allocation) ||
304 growth_policy == kForceGrowth) &&
305 CanIncreaseCapacityInWords(kPageSizeInWords)) {
306 HeapPage* page = AllocatePage(type);
307 ASSERT(page != NULL);
308 // Start of the newly allocated page is the allocated object.
309 result = page->object_start();
310 // Enqueue the remainder in the free list.
311 uword free_start = result + size;
312 intptr_t free_size = page->object_end() - free_start;
313 if (free_size > 0) {
314 if (is_locked) {
315 freelist_[type].FreeLocked(free_start, free_size);
316 } else {
317 freelist_[type].Free(free_start, free_size);
318 }
319 }
320 }
321 } 336 }
322 } else { 337 } else {
323 // Large page allocation. 338 // Large page allocation.
324 intptr_t page_size_in_words = LargePageSizeInWordsFor(size); 339 intptr_t page_size_in_words = LargePageSizeInWordsFor(size);
325 if ((page_size_in_words << kWordSizeLog2) < size) { 340 if ((page_size_in_words << kWordSizeLog2) < size) {
326 // On overflow we fail to allocate. 341 // On overflow we fail to allocate.
327 return 0; 342 return 0;
328 } 343 }
344 SpaceUsage after_allocation = usage_;
345 after_allocation.used_in_words += size >> kWordSizeLog2;
329 after_allocation.capacity_in_words += page_size_in_words; 346 after_allocation.capacity_in_words += page_size_in_words;
330 if ((!page_space_controller_.NeedsGarbageCollection(after_allocation) || 347 if ((growth_policy == kForceGrowth ||
331 growth_policy == kForceGrowth) && 348 !page_space_controller_.NeedsGarbageCollection(after_allocation)) &&
332 CanIncreaseCapacityInWords(page_size_in_words)) { 349 CanIncreaseCapacityInWords(page_size_in_words)) {
333 HeapPage* page = AllocateLargePage(size, type); 350 HeapPage* page = AllocateLargePage(size, type);
334 if (page != NULL) { 351 if (page != NULL) {
335 result = page->object_start(); 352 result = page->object_start();
353 usage_ = after_allocation;
336 } 354 }
337 } 355 }
338 } 356 }
339 if (result != 0) { 357 if (result != 0) {
340 usage_ = after_allocation;
341 if (FLAG_compiler_stats && (type == HeapPage::kExecutable)) { 358 if (FLAG_compiler_stats && (type == HeapPage::kExecutable)) {
342 CompilerStats::code_allocated += size; 359 CompilerStats::code_allocated += size;
343 } 360 }
344 } 361 }
345 ASSERT((result & kObjectAlignmentMask) == kOldObjectAlignmentOffset); 362 ASSERT((result & kObjectAlignmentMask) == kOldObjectAlignmentOffset);
346 return result; 363 return result;
347 } 364 }
348 365
349 366
350 void PageSpace::AcquireDataLock() { 367 void PageSpace::AcquireDataLock() {
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after
621 SpaceUsage usage_before = usage_; 638 SpaceUsage usage_before = usage_;
622 639
623 // Mark all reachable old-gen objects. 640 // Mark all reachable old-gen objects.
624 bool collect_code = FLAG_collect_code && ShouldCollectCode(); 641 bool collect_code = FLAG_collect_code && ShouldCollectCode();
625 GCMarker marker(heap_); 642 GCMarker marker(heap_);
626 marker.MarkObjects(isolate, this, invoke_api_callbacks, collect_code); 643 marker.MarkObjects(isolate, this, invoke_api_callbacks, collect_code);
627 usage_.used_in_words = marker.marked_words(); 644 usage_.used_in_words = marker.marked_words();
628 645
629 int64_t mid1 = OS::GetCurrentTimeMicros(); 646 int64_t mid1 = OS::GetCurrentTimeMicros();
630 647
631 // Reset the bump allocation page to unused. 648 // Abandon the remainder of the bump allocation block.
649 bump_top_ = bump_end_;
Ivan Posva 2014/08/29 00:07:12 Why not setting these values to 0?
koda 2014/08/29 00:52:20 Done.
632 // Reset the freelists and setup sweeping. 650 // Reset the freelists and setup sweeping.
633 freelist_[HeapPage::kData].Reset(); 651 freelist_[HeapPage::kData].Reset();
634 freelist_[HeapPage::kExecutable].Reset(); 652 freelist_[HeapPage::kExecutable].Reset();
635 653
636 int64_t mid2 = OS::GetCurrentTimeMicros(); 654 int64_t mid2 = OS::GetCurrentTimeMicros();
637 int64_t mid3 = 0; 655 int64_t mid3 = 0;
638 656
639 { 657 {
640 GCSweeper sweeper(heap_); 658 GCSweeper sweeper(heap_);
641 659
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
728 746
729 // Done, reset the task count. 747 // Done, reset the task count.
730 { 748 {
731 MonitorLocker ml(tasks_lock()); 749 MonitorLocker ml(tasks_lock());
732 set_tasks(tasks() - 1); 750 set_tasks(tasks() - 1);
733 ml.Notify(); 751 ml.Notify();
734 } 752 }
735 } 753 }
736 754
737 755
756 uword PageSpace::TryAllocateDataBump(intptr_t size,
757 GrowthPolicy growth_policy) {
758 ASSERT(size >= kObjectAlignment);
759 ASSERT(Utils::IsAligned(size, kObjectAlignment));
760 intptr_t remaining = bump_end_ - bump_top_;
761 if (remaining < size) {
762 if (size >= kAllocatablePageSize) {
Ivan Posva 2014/08/29 00:07:12 Please explain in a comment why this is not done a
koda 2014/08/29 00:52:20 Done.
763 return TryAllocate(size, HeapPage::kData, growth_policy);
764 }
765 FreeListElement* block = freelist_[HeapPage::kData].TryAllocateLarge(size);
766 if (block == NULL) {
767 // Allocating from a new page (if growth policy allows) will have the
768 // side-effect of populating the freelist with a large block.
Ivan Posva 2014/08/29 00:07:12 ...with a large block. Next time we request bump a
koda 2014/08/29 00:52:20 Done.
769 // TODO(koda): Could take freelist lock just once instead of twice.
770 return TryAllocateInNewPage(size,
771 HeapPage::kData,
772 growth_policy,
773 /* is_locked = */ false);
774 }
775 intptr_t block_size = block->Size();
776 bump_top_ = reinterpret_cast<uword>(block);
777 bump_end_ = bump_top_ + block_size;
778 remaining = block_size;
779 }
780 ASSERT(remaining >= size);
781 uword result = bump_top_;
782 bump_top_ += size;
783 usage_.used_in_words += size >> kWordSizeLog2;
784 remaining -= size;
785 if (remaining > 0) {
786 FreeListElement::AsElement(bump_top_, remaining);
787 }
788 return result;
789 }
790
791
738 PageSpaceController::PageSpaceController(Heap* heap, 792 PageSpaceController::PageSpaceController(Heap* heap,
739 int heap_growth_ratio, 793 int heap_growth_ratio,
740 int heap_growth_max, 794 int heap_growth_max,
741 int garbage_collection_time_ratio) 795 int garbage_collection_time_ratio)
742 : heap_(heap), 796 : heap_(heap),
743 is_enabled_(false), 797 is_enabled_(false),
744 grow_heap_(heap_growth_max / 2), 798 grow_heap_(heap_growth_max / 2),
745 heap_growth_ratio_(heap_growth_ratio), 799 heap_growth_ratio_(heap_growth_ratio),
746 desired_utilization_((100.0 - heap_growth_ratio) / 100.0), 800 desired_utilization_((100.0 - heap_growth_ratio) / 100.0),
747 heap_growth_max_(heap_growth_max), 801 heap_growth_max_(heap_growth_max),
(...skipping 25 matching lines...) Expand all
773 // To avoid waste, the first GC should be triggered before too long. After 827 // To avoid waste, the first GC should be triggered before too long. After
774 // kInitialTimeoutSeconds, gradually lower the capacity limit. 828 // kInitialTimeoutSeconds, gradually lower the capacity limit.
775 static const double kInitialTimeoutSeconds = 1.00; 829 static const double kInitialTimeoutSeconds = 1.00;
776 if (history_.IsEmpty()) { 830 if (history_.IsEmpty()) {
777 double seconds_since_init = MicrosecondsToSeconds( 831 double seconds_since_init = MicrosecondsToSeconds(
778 OS::GetCurrentTimeMicros() - heap_->isolate()->start_time()); 832 OS::GetCurrentTimeMicros() - heap_->isolate()->start_time());
779 if (seconds_since_init > kInitialTimeoutSeconds) { 833 if (seconds_since_init > kInitialTimeoutSeconds) {
780 multiplier *= seconds_since_init / kInitialTimeoutSeconds; 834 multiplier *= seconds_since_init / kInitialTimeoutSeconds;
781 } 835 }
782 } 836 }
783 return capacity_increase_in_pages * multiplier > grow_heap_; 837 bool needs_gc = capacity_increase_in_pages * multiplier > grow_heap_;
838 if (FLAG_log_growth) {
839 OS::PrintErr("%s: %" Pd " * %f %s %" Pd "\n",
840 needs_gc ? "NEEDS GC" : "grow",
841 capacity_increase_in_pages,
842 multiplier,
843 needs_gc ? ">" : "<=",
844 grow_heap_);
845 }
846 return needs_gc;
784 } 847 }
785 848
786 849
787 void PageSpaceController::EvaluateGarbageCollection( 850 void PageSpaceController::EvaluateGarbageCollection(
788 SpaceUsage before, SpaceUsage after, int64_t start, int64_t end) { 851 SpaceUsage before, SpaceUsage after, int64_t start, int64_t end) {
789 ASSERT(end >= start); 852 ASSERT(end >= start);
790 history_.AddGarbageCollectionTime(start, end); 853 history_.AddGarbageCollectionTime(start, end);
791 int gc_time_fraction = history_.GarbageCollectionTimeFraction(); 854 int gc_time_fraction = history_.GarbageCollectionTimeFraction();
792 heap_->RecordData(PageSpace::kGCTimeFraction, gc_time_fraction); 855 heap_->RecordData(PageSpace::kGCTimeFraction, gc_time_fraction);
793 856
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
851 return 0; 914 return 0;
852 } else { 915 } else {
853 ASSERT(total_time >= gc_time); 916 ASSERT(total_time >= gc_time);
854 int result= static_cast<int>((static_cast<double>(gc_time) / 917 int result= static_cast<int>((static_cast<double>(gc_time) /
855 static_cast<double>(total_time)) * 100); 918 static_cast<double>(total_time)) * 100);
856 return result; 919 return result;
857 } 920 }
858 } 921 }
859 922
860 } // namespace dart 923 } // namespace dart
OLDNEW
« runtime/vm/freelist.cc ('K') | « runtime/vm/pages.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698