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

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

Issue 474913004: - Account for number of pending tasks in old-space collections. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 4 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
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"
11 #include "vm/lockers.h"
11 #include "vm/object.h" 12 #include "vm/object.h"
13 #include "vm/thread.h"
12 #include "vm/virtual_memory.h" 14 #include "vm/virtual_memory.h"
13 15
14 namespace dart { 16 namespace dart {
15 17
16 DEFINE_FLAG(int, heap_growth_space_ratio, 20, 18 DEFINE_FLAG(int, heap_growth_space_ratio, 20,
17 "The desired maximum percentage of free space after GC"); 19 "The desired maximum percentage of free space after GC");
18 DEFINE_FLAG(int, heap_growth_time_ratio, 3, 20 DEFINE_FLAG(int, heap_growth_time_ratio, 3,
19 "The desired maximum percentage of time spent in GC"); 21 "The desired maximum percentage of time spent in GC");
20 DEFINE_FLAG(int, heap_growth_rate, 256, 22 DEFINE_FLAG(int, heap_growth_rate, 256,
21 "The max number of pages the heap can grow at a time"); 23 "The max number of pages the heap can grow at a time");
22 DEFINE_FLAG(bool, print_free_list_before_gc, false, 24 DEFINE_FLAG(bool, print_free_list_before_gc, false,
23 "Print free list statistics before a GC"); 25 "Print free list statistics before a GC");
24 DEFINE_FLAG(bool, print_free_list_after_gc, false, 26 DEFINE_FLAG(bool, print_free_list_after_gc, false,
25 "Print free list statistics after a GC"); 27 "Print free list statistics after a GC");
26 DEFINE_FLAG(bool, collect_code, true, 28 DEFINE_FLAG(bool, collect_code, true,
27 "Attempt to GC infrequently used code."); 29 "Attempt to GC infrequently used code.");
28 DEFINE_FLAG(int, code_collection_interval_in_us, 30000000, 30 DEFINE_FLAG(int, code_collection_interval_in_us, 30000000,
29 "Time between attempts to collect unused code."); 31 "Time between attempts to collect unused code.");
30 DEFINE_FLAG(bool, log_code_drop, false, 32 DEFINE_FLAG(bool, log_code_drop, false,
31 "Emit a log message when pointers to unused code are dropped."); 33 "Emit a log message when pointers to unused code are dropped.");
32 DEFINE_FLAG(bool, always_drop_code, false, 34 DEFINE_FLAG(bool, always_drop_code, false,
33 "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");
34 DECLARE_FLAG(bool, write_protect_code);
35 36
36 HeapPage* HeapPage::Initialize(VirtualMemory* memory, PageType type) { 37 HeapPage* HeapPage::Initialize(VirtualMemory* memory, PageType type) {
37 ASSERT(memory->size() > VirtualMemory::PageSize()); 38 ASSERT(memory->size() > VirtualMemory::PageSize());
38 bool is_executable = (type == kExecutable); 39 bool is_executable = (type == kExecutable);
39 memory->Commit(is_executable); 40 memory->Commit(is_executable);
40 41
41 HeapPage* result = reinterpret_cast<HeapPage*>(memory->address()); 42 HeapPage* result = reinterpret_cast<HeapPage*>(memory->address());
42 result->memory_ = memory; 43 result->memory_ = memory;
43 result->next_ = NULL; 44 result->next_ = NULL;
44 result->executable_ = is_executable; 45 result->executable_ = is_executable;
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
117 } 118 }
118 119
119 120
120 PageSpace::PageSpace(Heap* heap, intptr_t max_capacity_in_words) 121 PageSpace::PageSpace(Heap* heap, intptr_t max_capacity_in_words)
121 : freelist_(), 122 : freelist_(),
122 heap_(heap), 123 heap_(heap),
123 pages_(NULL), 124 pages_(NULL),
124 pages_tail_(NULL), 125 pages_tail_(NULL),
125 large_pages_(NULL), 126 large_pages_(NULL),
126 max_capacity_in_words_(max_capacity_in_words), 127 max_capacity_in_words_(max_capacity_in_words),
127 sweeping_(false), 128 tasks_lock_(new Monitor()),
129 tasks_(0),
128 page_space_controller_(heap, 130 page_space_controller_(heap,
129 FLAG_heap_growth_space_ratio, 131 FLAG_heap_growth_space_ratio,
130 FLAG_heap_growth_rate, 132 FLAG_heap_growth_rate,
131 FLAG_heap_growth_time_ratio), 133 FLAG_heap_growth_time_ratio),
132 gc_time_micros_(0), 134 gc_time_micros_(0),
133 collections_(0) { 135 collections_(0) {
134 } 136 }
135 137
136 138
137 PageSpace::~PageSpace() { 139 PageSpace::~PageSpace() {
140 {
141 MonitorLocker ml(tasks_lock());
142 ASSERT(tasks() == 0);
143 }
138 FreePages(pages_); 144 FreePages(pages_);
139 FreePages(large_pages_); 145 FreePages(large_pages_);
146 delete tasks_lock_;
140 } 147 }
141 148
142 149
143 intptr_t PageSpace::LargePageSizeInWordsFor(intptr_t size) { 150 intptr_t PageSpace::LargePageSizeInWordsFor(intptr_t size) {
144 intptr_t page_size = Utils::RoundUp(size + HeapPage::ObjectStartOffset(), 151 intptr_t page_size = Utils::RoundUp(size + HeapPage::ObjectStartOffset(),
145 VirtualMemory::PageSize()); 152 VirtualMemory::PageSize());
146 return page_size >> kWordSizeLog2; 153 return page_size >> kWordSizeLog2;
147 } 154 }
148 155
149 156
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 void PageSpace::FreePages(HeapPage* pages) { 238 void PageSpace::FreePages(HeapPage* pages) {
232 HeapPage* page = pages; 239 HeapPage* page = pages;
233 while (page != NULL) { 240 while (page != NULL) {
234 HeapPage* next = page->next(); 241 HeapPage* next = page->next();
235 page->Deallocate(); 242 page->Deallocate();
236 page = next; 243 page = next;
237 } 244 }
238 } 245 }
239 246
240 247
241 uword PageSpace::TryAllocate(intptr_t size, 248 uword PageSpace::TryAllocateInternal(intptr_t size,
242 HeapPage::PageType type, 249 HeapPage::PageType type,
243 GrowthPolicy growth_policy) { 250 GrowthPolicy growth_policy,
251 bool is_protected,
252 bool is_locked) {
244 ASSERT(size >= kObjectAlignment); 253 ASSERT(size >= kObjectAlignment);
245 ASSERT(Utils::IsAligned(size, kObjectAlignment)); 254 ASSERT(Utils::IsAligned(size, kObjectAlignment));
246 uword result = 0; 255 uword result = 0;
247 SpaceUsage after_allocation = usage_; 256 SpaceUsage after_allocation = usage_;
248 after_allocation.used_in_words += size >> kWordSizeLog2; 257 after_allocation.used_in_words += size >> kWordSizeLog2;
249 if (size < kAllocatablePageSize) { 258 if (size < kAllocatablePageSize) {
250 const bool is_protected = (type == HeapPage::kExecutable) 259 if (is_locked) {
251 && FLAG_write_protect_code; 260 result = freelist_[type].TryAllocateLocked(size, is_protected);
252 result = freelist_[type].TryAllocate(size, is_protected); 261 } else {
262 result = freelist_[type].TryAllocate(size, is_protected);
263 }
253 if (result == 0) { 264 if (result == 0) {
254 // Can we grow by one page? 265 // Can we grow by one page?
255 after_allocation.capacity_in_words += kPageSizeInWords; 266 after_allocation.capacity_in_words += kPageSizeInWords;
256 if ((!page_space_controller_.NeedsGarbageCollection(after_allocation) || 267 if ((!page_space_controller_.NeedsGarbageCollection(after_allocation) ||
257 growth_policy == kForceGrowth) && 268 growth_policy == kForceGrowth) &&
258 CanIncreaseCapacityInWords(kPageSizeInWords)) { 269 CanIncreaseCapacityInWords(kPageSizeInWords)) {
259 HeapPage* page = AllocatePage(type); 270 HeapPage* page = AllocatePage(type);
260 ASSERT(page != NULL); 271 ASSERT(page != NULL);
261 // Start of the newly allocated page is the allocated object. 272 // Start of the newly allocated page is the allocated object.
262 result = page->object_start(); 273 result = page->object_start();
263 // Enqueue the remainder in the free list. 274 // Enqueue the remainder in the free list.
264 uword free_start = result + size; 275 uword free_start = result + size;
265 intptr_t free_size = page->object_end() - free_start; 276 intptr_t free_size = page->object_end() - free_start;
266 if (free_size > 0) { 277 if (free_size > 0) {
267 freelist_[type].Free(free_start, free_size); 278 if (is_locked) {
279 freelist_[type].FreeLocked(free_start, free_size);
280 } else {
281 freelist_[type].Free(free_start, free_size);
282 }
268 } 283 }
269 } 284 }
270 } 285 }
271 } else { 286 } else {
272 // Large page allocation. 287 // Large page allocation.
273 intptr_t page_size_in_words = LargePageSizeInWordsFor(size); 288 intptr_t page_size_in_words = LargePageSizeInWordsFor(size);
274 if ((page_size_in_words << kWordSizeLog2) < size) { 289 if ((page_size_in_words << kWordSizeLog2) < size) {
275 // On overflow we fail to allocate. 290 // On overflow we fail to allocate.
276 return 0; 291 return 0;
277 } 292 }
(...skipping 11 matching lines...) Expand all
289 usage_ = after_allocation; 304 usage_ = after_allocation;
290 if (FLAG_compiler_stats && (type == HeapPage::kExecutable)) { 305 if (FLAG_compiler_stats && (type == HeapPage::kExecutable)) {
291 CompilerStats::code_allocated += size; 306 CompilerStats::code_allocated += size;
292 } 307 }
293 } 308 }
294 ASSERT((result & kObjectAlignmentMask) == kOldObjectAlignmentOffset); 309 ASSERT((result & kObjectAlignmentMask) == kOldObjectAlignmentOffset);
295 return result; 310 return result;
296 } 311 }
297 312
298 313
314 void PageSpace::AcquireDataLock() {
315 freelist_[HeapPage::kData].mutex()->Lock();
316 }
317
318
319 void PageSpace::ReleaseDataLock() {
320 freelist_[HeapPage::kData].mutex()->Unlock();
321 }
322
323
299 void PageSpace::AllocateExternal(intptr_t size) { 324 void PageSpace::AllocateExternal(intptr_t size) {
300 intptr_t size_in_words = size >> kWordSizeLog2; 325 intptr_t size_in_words = size >> kWordSizeLog2;
301 usage_.external_in_words += size_in_words; 326 usage_.external_in_words += size_in_words;
302 // TODO(koda): Control growth. 327 // TODO(koda): Control growth.
303 } 328 }
304 329
305 330
306 void PageSpace::FreeExternal(intptr_t size) { 331 void PageSpace::FreeExternal(intptr_t size) {
307 intptr_t size_in_words = size >> kWordSizeLog2; 332 intptr_t size_in_words = size >> kWordSizeLog2;
308 usage_.external_in_words -= size_in_words; 333 usage_.external_in_words -= size_in_words;
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
484 if (current_page->type() == HeapPage::kExecutable) { 509 if (current_page->type() == HeapPage::kExecutable) {
485 current_page->WriteProtect(read_only); 510 current_page->WriteProtect(read_only);
486 } 511 }
487 current_page = NextPageAnySize(current_page); 512 current_page = NextPageAnySize(current_page);
488 } 513 }
489 } 514 }
490 } 515 }
491 516
492 517
493 void PageSpace::MarkSweep(bool invoke_api_callbacks) { 518 void PageSpace::MarkSweep(bool invoke_api_callbacks) {
494 // MarkSweep is not reentrant. Make sure that is the case. 519 Isolate* isolate = heap_->isolate();
495 ASSERT(!sweeping_); 520 ASSERT(isolate == Isolate::Current());
496 sweeping_ = true; 521
497 Isolate* isolate = Isolate::Current(); 522 // Wait for pending tasks to complete and then account for the driver task.
523 {
524 MonitorLocker locker(tasks_lock());
525 while (tasks() != 0) {
526 locker.Wait();
527 }
528 set_tasks(1);
529 }
498 530
499 NoHandleScope no_handles(isolate); 531 NoHandleScope no_handles(isolate);
500 532
501 if (FLAG_print_free_list_before_gc) { 533 if (FLAG_print_free_list_before_gc) {
502 OS::Print("Data Freelist (before GC):\n"); 534 OS::Print("Data Freelist (before GC):\n");
503 freelist_[HeapPage::kData].Print(); 535 freelist_[HeapPage::kData].Print();
504 OS::Print("Executable Freelist (before GC):\n"); 536 OS::Print("Executable Freelist (before GC):\n");
505 freelist_[HeapPage::kExecutable].Print(); 537 freelist_[HeapPage::kExecutable].Print();
506 } 538 }
507 539
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
587 OS::Print("Executable Freelist (after GC):\n"); 619 OS::Print("Executable Freelist (after GC):\n");
588 freelist_[HeapPage::kExecutable].Print(); 620 freelist_[HeapPage::kExecutable].Print();
589 } 621 }
590 622
591 if (FLAG_verify_after_gc) { 623 if (FLAG_verify_after_gc) {
592 OS::PrintErr("Verifying after MarkSweep..."); 624 OS::PrintErr("Verifying after MarkSweep...");
593 heap_->Verify(); 625 heap_->Verify();
594 OS::PrintErr(" done.\n"); 626 OS::PrintErr(" done.\n");
595 } 627 }
596 628
597 // Done, reset the marker. 629 // Done, reset the task count.
598 ASSERT(sweeping_); 630 {
599 sweeping_ = false; 631 MonitorLocker locker(tasks_lock());
632 ASSERT(tasks() == 1);
633 set_tasks(tasks() - 1);
634 }
600 } 635 }
601 636
602 637
603 PageSpaceController::PageSpaceController(Heap* heap, 638 PageSpaceController::PageSpaceController(Heap* heap,
604 int heap_growth_ratio, 639 int heap_growth_ratio,
605 int heap_growth_max, 640 int heap_growth_max,
606 int garbage_collection_time_ratio) 641 int garbage_collection_time_ratio)
607 : heap_(heap), 642 : heap_(heap),
608 is_enabled_(false), 643 is_enabled_(false),
609 grow_heap_(heap_growth_max / 2), 644 grow_heap_(heap_growth_max / 2),
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
714 return 0; 749 return 0;
715 } else { 750 } else {
716 ASSERT(total_time >= gc_time); 751 ASSERT(total_time >= gc_time);
717 int result= static_cast<int>((static_cast<double>(gc_time) / 752 int result= static_cast<int>((static_cast<double>(gc_time) /
718 static_cast<double>(total_time)) * 100); 753 static_cast<double>(total_time)) * 100);
719 return result; 754 return result;
720 } 755 }
721 } 756 }
722 757
723 } // namespace dart 758 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698