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 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
111 | 111 |
112 PageSpace::PageSpace(Heap* heap, intptr_t max_capacity) | 112 PageSpace::PageSpace(Heap* heap, intptr_t max_capacity) |
113 : freelist_(), | 113 : freelist_(), |
114 heap_(heap), | 114 heap_(heap), |
115 pages_(NULL), | 115 pages_(NULL), |
116 pages_tail_(NULL), | 116 pages_tail_(NULL), |
117 large_pages_(NULL), | 117 large_pages_(NULL), |
118 max_capacity_(max_capacity), | 118 max_capacity_(max_capacity), |
119 capacity_(0), | 119 capacity_(0), |
120 in_use_(0), | 120 in_use_(0), |
121 count_(0), | |
122 sweeping_(false), | 121 sweeping_(false), |
123 page_space_controller_(FLAG_heap_growth_space_ratio, | 122 page_space_controller_(FLAG_heap_growth_space_ratio, |
124 FLAG_heap_growth_rate, | 123 FLAG_heap_growth_rate, |
125 FLAG_heap_growth_time_ratio) { | 124 FLAG_heap_growth_time_ratio) { |
126 } | 125 } |
127 | 126 |
128 | 127 |
129 PageSpace::~PageSpace() { | 128 PageSpace::~PageSpace() { |
130 FreePages(pages_); | 129 FreePages(pages_); |
131 FreePages(large_pages_); | 130 FreePages(large_pages_); |
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
395 page = page->next(); | 394 page = page->next(); |
396 } | 395 } |
397 page = large_pages_; | 396 page = large_pages_; |
398 while (page != NULL) { | 397 while (page != NULL) { |
399 page->WriteProtect(read_only); | 398 page->WriteProtect(read_only); |
400 page = page->next(); | 399 page = page->next(); |
401 } | 400 } |
402 } | 401 } |
403 | 402 |
404 | 403 |
405 void PageSpace::MarkSweep(bool invoke_api_callbacks, const char* gc_reason) { | 404 void PageSpace::MarkSweep(bool invoke_api_callbacks) { |
406 // MarkSweep is not reentrant. Make sure that is the case. | 405 // MarkSweep is not reentrant. Make sure that is the case. |
407 ASSERT(!sweeping_); | 406 ASSERT(!sweeping_); |
408 sweeping_ = true; | 407 sweeping_ = true; |
409 Isolate* isolate = Isolate::Current(); | 408 Isolate* isolate = Isolate::Current(); |
410 NoHandleScope no_handles(isolate); | 409 NoHandleScope no_handles(isolate); |
411 | 410 |
412 if (HeapTrace::is_enabled()) { | 411 if (HeapTrace::is_enabled()) { |
413 isolate->heap()->trace()->TraceMarkSweepStart(); | 412 isolate->heap()->trace()->TraceMarkSweepStart(); |
414 } | 413 } |
415 | 414 |
416 if (FLAG_print_free_list_before_gc) { | 415 if (FLAG_print_free_list_before_gc) { |
417 OS::Print("Data Freelist (before GC):\n"); | 416 OS::Print("Data Freelist (before GC):\n"); |
418 freelist_[HeapPage::kData].Print(); | 417 freelist_[HeapPage::kData].Print(); |
419 OS::Print("Executable Freelist (before GC):\n"); | 418 OS::Print("Executable Freelist (before GC):\n"); |
420 freelist_[HeapPage::kExecutable].Print(); | 419 freelist_[HeapPage::kExecutable].Print(); |
421 } | 420 } |
422 | 421 |
423 if (FLAG_verify_before_gc) { | 422 if (FLAG_verify_before_gc) { |
424 OS::PrintErr("Verifying before MarkSweep..."); | 423 OS::PrintErr("Verifying before MarkSweep..."); |
425 heap_->Verify(); | 424 heap_->Verify(); |
426 OS::PrintErr(" done.\n"); | 425 OS::PrintErr(" done.\n"); |
427 } | 426 } |
428 | 427 |
429 if (FLAG_verbose_gc) { | 428 int64_t start = OS::GetCurrentTimeMicros(); |
430 OS::PrintErr("Start mark sweep for %s collection\n", gc_reason); | |
431 } | |
432 Timer timer(true, "MarkSweep"); | |
433 timer.Start(); | |
434 int64_t start = OS::GetCurrentTimeMillis(); | |
435 | 429 |
436 // Mark all reachable old-gen objects. | 430 // Mark all reachable old-gen objects. |
437 GCMarker marker(heap_); | 431 GCMarker marker(heap_); |
438 marker.MarkObjects(isolate, this, invoke_api_callbacks); | 432 marker.MarkObjects(isolate, this, invoke_api_callbacks); |
439 | 433 |
| 434 int64_t mid1 = OS::GetCurrentTimeMicros(); |
| 435 |
440 // Reset the bump allocation page to unused. | 436 // Reset the bump allocation page to unused. |
441 // Reset the freelists and setup sweeping. | 437 // Reset the freelists and setup sweeping. |
442 freelist_[HeapPage::kData].Reset(); | 438 freelist_[HeapPage::kData].Reset(); |
443 freelist_[HeapPage::kExecutable].Reset(); | 439 freelist_[HeapPage::kExecutable].Reset(); |
| 440 |
| 441 int64_t mid2 = OS::GetCurrentTimeMicros(); |
| 442 |
444 GCSweeper sweeper(heap_); | 443 GCSweeper sweeper(heap_); |
445 intptr_t in_use = 0; | 444 intptr_t in_use = 0; |
446 | 445 |
447 HeapPage* prev_page = NULL; | 446 HeapPage* prev_page = NULL; |
448 HeapPage* page = pages_; | 447 HeapPage* page = pages_; |
449 while (page != NULL) { | 448 while (page != NULL) { |
450 HeapPage* next_page = page->next(); | 449 HeapPage* next_page = page->next(); |
451 intptr_t page_in_use = sweeper.SweepPage(page, &freelist_[page->type()]); | 450 intptr_t page_in_use = sweeper.SweepPage(page, &freelist_[page->type()]); |
452 if (page_in_use == 0) { | 451 if (page_in_use == 0) { |
453 FreePage(page, prev_page); | 452 FreePage(page, prev_page); |
454 } else { | 453 } else { |
455 in_use += page_in_use; | 454 in_use += page_in_use; |
456 prev_page = page; | 455 prev_page = page; |
457 } | 456 } |
458 // Advance to the next page. | 457 // Advance to the next page. |
459 page = next_page; | 458 page = next_page; |
460 } | 459 } |
461 | 460 |
| 461 int64_t mid3 = OS::GetCurrentTimeMicros(); |
| 462 |
462 prev_page = NULL; | 463 prev_page = NULL; |
463 page = large_pages_; | 464 page = large_pages_; |
464 while (page != NULL) { | 465 while (page != NULL) { |
465 intptr_t page_in_use = sweeper.SweepLargePage(page); | 466 intptr_t page_in_use = sweeper.SweepLargePage(page); |
466 HeapPage* next_page = page->next(); | 467 HeapPage* next_page = page->next(); |
467 if (page_in_use == 0) { | 468 if (page_in_use == 0) { |
468 FreeLargePage(page, prev_page); | 469 FreeLargePage(page, prev_page); |
469 } else { | 470 } else { |
470 in_use += page_in_use; | 471 in_use += page_in_use; |
471 prev_page = page; | 472 prev_page = page; |
472 } | 473 } |
473 // Advance to the next page. | 474 // Advance to the next page. |
474 page = next_page; | 475 page = next_page; |
475 } | 476 } |
476 | 477 |
477 // Record data and print if requested. | 478 // Record data and print if requested. |
478 intptr_t in_use_before = in_use_; | 479 intptr_t in_use_before = in_use_; |
479 in_use_ = in_use; | 480 in_use_ = in_use; |
480 | 481 |
481 int64_t end = OS::GetCurrentTimeMillis(); | 482 int64_t end = OS::GetCurrentTimeMicros(); |
482 timer.Stop(); | |
483 | 483 |
484 // Record signals for growth control. | 484 // Record signals for growth control. |
485 page_space_controller_.EvaluateGarbageCollection(in_use_before, in_use, | 485 page_space_controller_.EvaluateGarbageCollection(in_use_before, in_use, |
486 start, end); | 486 start, end); |
487 | 487 |
488 if (FLAG_verbose_gc) { | 488 heap_->RecordTime(0, mid1 - start); |
489 const intptr_t KB2 = KB / 2; | 489 heap_->RecordTime(1, mid2 - mid1); |
490 OS::PrintErr("Mark-Sweep[%d]: %"Pd64"us (%"Pd"K -> %"Pd"K, %"Pd"K)\n", | 490 heap_->RecordTime(2, mid3 - mid2); |
491 count_, | 491 heap_->RecordTime(3, end - mid3); |
492 timer.TotalElapsedTime(), | |
493 (in_use_before + (KB2)) / KB, | |
494 (in_use + (KB2)) / KB, | |
495 (capacity_ + KB2) / KB); | |
496 } | |
497 | 492 |
498 if (FLAG_print_free_list_after_gc) { | 493 if (FLAG_print_free_list_after_gc) { |
499 OS::Print("Data Freelist (after GC):\n"); | 494 OS::Print("Data Freelist (after GC):\n"); |
500 freelist_[HeapPage::kData].Print(); | 495 freelist_[HeapPage::kData].Print(); |
501 OS::Print("Executable Freelist (after GC):\n"); | 496 OS::Print("Executable Freelist (after GC):\n"); |
502 freelist_[HeapPage::kExecutable].Print(); | 497 freelist_[HeapPage::kExecutable].Print(); |
503 } | 498 } |
504 | 499 |
505 if (FLAG_verify_after_gc) { | 500 if (FLAG_verify_after_gc) { |
506 OS::PrintErr("Verifying after MarkSweep..."); | 501 OS::PrintErr("Verifying after MarkSweep..."); |
507 heap_->Verify(); | 502 heap_->Verify(); |
508 OS::PrintErr(" done.\n"); | 503 OS::PrintErr(" done.\n"); |
509 } | 504 } |
510 | 505 |
511 if (HeapTrace::is_enabled()) { | 506 if (HeapTrace::is_enabled()) { |
512 isolate->heap()->trace()->TraceMarkSweepFinish(); | 507 isolate->heap()->trace()->TraceMarkSweepFinish(); |
513 } | 508 } |
514 | 509 |
515 count_++; | |
516 // Done, reset the marker. | 510 // Done, reset the marker. |
517 ASSERT(sweeping_); | 511 ASSERT(sweeping_); |
518 sweeping_ = false; | 512 sweeping_ = false; |
519 } | 513 } |
520 | 514 |
521 | 515 |
522 PageSpaceController::PageSpaceController(int heap_growth_ratio, | 516 PageSpaceController::PageSpaceController(int heap_growth_ratio, |
523 int heap_growth_rate, | 517 int heap_growth_rate, |
524 int garbage_collection_time_ratio) | 518 int garbage_collection_time_ratio) |
525 : is_enabled_(false), | 519 : is_enabled_(false), |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
559 int collected_garbage_ratio = | 553 int collected_garbage_ratio = |
560 static_cast<int>((static_cast<double>(in_use_before - in_use_after) / | 554 static_cast<int>((static_cast<double>(in_use_before - in_use_after) / |
561 static_cast<double>(in_use_before)) | 555 static_cast<double>(in_use_before)) |
562 * 100.0); | 556 * 100.0); |
563 bool enough_free_space = | 557 bool enough_free_space = |
564 (collected_garbage_ratio >= heap_growth_ratio_); | 558 (collected_garbage_ratio >= heap_growth_ratio_); |
565 int garbage_collection_time_fraction = | 559 int garbage_collection_time_fraction = |
566 history_.GarbageCollectionTimeFraction(); | 560 history_.GarbageCollectionTimeFraction(); |
567 bool enough_free_time = | 561 bool enough_free_time = |
568 (garbage_collection_time_fraction <= garbage_collection_time_ratio_); | 562 (garbage_collection_time_fraction <= garbage_collection_time_ratio_); |
| 563 |
| 564 Heap* heap = Isolate::Current()->heap(); |
569 if (enough_free_space && enough_free_time) { | 565 if (enough_free_space && enough_free_time) { |
570 grow_heap_ = 0; | 566 grow_heap_ = 0; |
571 } else { | 567 } else { |
572 if (FLAG_verbose_gc) { | |
573 OS::PrintErr("PageSpaceController: "); | |
574 if (!enough_free_space) { | |
575 OS::PrintErr("free space %d%% < %d%%", | |
576 collected_garbage_ratio, | |
577 heap_growth_ratio_); | |
578 } | |
579 if (!enough_free_space && !enough_free_time) { | |
580 OS::PrintErr(", "); | |
581 } | |
582 if (!enough_free_time) { | |
583 OS::PrintErr("garbage collection time %d%% > %d%%", | |
584 garbage_collection_time_fraction, | |
585 garbage_collection_time_ratio_); | |
586 } | |
587 OS::PrintErr("\n"); | |
588 } | |
589 intptr_t growth_target = static_cast<intptr_t>(in_use_after / | 568 intptr_t growth_target = static_cast<intptr_t>(in_use_after / |
590 desired_utilization_); | 569 desired_utilization_); |
591 intptr_t growth_in_bytes = Utils::RoundUp(growth_target - in_use_after, | 570 intptr_t growth_in_bytes = Utils::RoundUp(growth_target - in_use_after, |
592 PageSpace::kPageSize); | 571 PageSpace::kPageSize); |
593 int growth_in_pages = growth_in_bytes / PageSpace::kPageSize; | 572 int growth_in_pages = growth_in_bytes / PageSpace::kPageSize; |
594 grow_heap_ = Utils::Maximum(growth_in_pages, heap_growth_rate_); | 573 grow_heap_ = Utils::Maximum(growth_in_pages, heap_growth_rate_); |
| 574 heap->RecordData(2, growth_in_pages); |
595 } | 575 } |
| 576 heap->RecordData(0, collected_garbage_ratio); |
| 577 heap->RecordData(1, garbage_collection_time_fraction); |
| 578 heap->RecordData(3, grow_heap_); |
596 } | 579 } |
597 | 580 |
598 | 581 |
599 PageSpaceGarbageCollectionHistory::PageSpaceGarbageCollectionHistory() | 582 PageSpaceGarbageCollectionHistory::PageSpaceGarbageCollectionHistory() |
600 : index_(0) { | 583 : index_(0) { |
601 for (intptr_t i = 0; i < kHistoryLength; i++) { | 584 for (intptr_t i = 0; i < kHistoryLength; i++) { |
602 start_[i] = 0; | 585 start_[i] = 0; |
603 end_[i] = 0; | 586 end_[i] = 0; |
604 } | 587 } |
605 } | 588 } |
(...skipping 27 matching lines...) Expand all Loading... |
633 return 0; | 616 return 0; |
634 } else { | 617 } else { |
635 ASSERT(total_time >= gc_time); | 618 ASSERT(total_time >= gc_time); |
636 int result= static_cast<int>((static_cast<double>(gc_time) / | 619 int result= static_cast<int>((static_cast<double>(gc_time) / |
637 static_cast<double>(total_time)) * 100); | 620 static_cast<double>(total_time)) * 100); |
638 return result; | 621 return result; |
639 } | 622 } |
640 } | 623 } |
641 | 624 |
642 } // namespace dart | 625 } // namespace dart |
OLD | NEW |