| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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/gc_marker.h" | 5 #include "vm/gc_marker.h" |
| 6 | 6 |
| 7 #include <map> | 7 #include <map> |
| 8 #include <utility> | 8 #include <utility> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| 11 #include "vm/allocation.h" | 11 #include "vm/allocation.h" |
| 12 #include "vm/dart_api_state.h" | 12 #include "vm/dart_api_state.h" |
| 13 #include "vm/isolate.h" | 13 #include "vm/isolate.h" |
| 14 #include "vm/log.h" | 14 #include "vm/log.h" |
| 15 #include "vm/pages.h" | 15 #include "vm/pages.h" |
| 16 #include "vm/raw_object.h" | 16 #include "vm/raw_object.h" |
| 17 #include "vm/stack_frame.h" | 17 #include "vm/stack_frame.h" |
| 18 #include "vm/store_buffer.h" | 18 #include "vm/store_buffer.h" |
| 19 #include "vm/thread_barrier.h" |
| 19 #include "vm/thread_pool.h" | 20 #include "vm/thread_pool.h" |
| 20 #include "vm/visitor.h" | 21 #include "vm/visitor.h" |
| 21 #include "vm/object_id_ring.h" | 22 #include "vm/object_id_ring.h" |
| 22 | 23 |
| 23 namespace dart { | 24 namespace dart { |
| 24 | 25 |
| 25 DEFINE_FLAG(int, marker_tasks, 1, | 26 DEFINE_FLAG(int, marker_tasks, 1, |
| 26 "The number of tasks to spawn during old gen GC marking (0 means " | 27 "The number of tasks to spawn during old gen GC marking (0 means " |
| 27 "perform all marking on main thread)."); | 28 "perform all marking on main thread)."); |
| 28 | 29 |
| (...skipping 517 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 546 | 547 |
| 547 | 548 |
| 548 class MarkTask : public ThreadPool::Task { | 549 class MarkTask : public ThreadPool::Task { |
| 549 public: | 550 public: |
| 550 MarkTask(GCMarker* marker, | 551 MarkTask(GCMarker* marker, |
| 551 Isolate* isolate, | 552 Isolate* isolate, |
| 552 Heap* heap, | 553 Heap* heap, |
| 553 PageSpace* page_space, | 554 PageSpace* page_space, |
| 554 MarkingStack* marking_stack, | 555 MarkingStack* marking_stack, |
| 555 DelaySet* delay_set, | 556 DelaySet* delay_set, |
| 557 ThreadBarrier* barrier, |
| 556 bool collect_code, | 558 bool collect_code, |
| 557 bool visit_prologue_weak_persistent_handles) | 559 bool visit_prologue_weak_persistent_handles) |
| 558 : marker_(marker), | 560 : marker_(marker), |
| 559 isolate_(isolate), | 561 isolate_(isolate), |
| 560 heap_(heap), | 562 heap_(heap), |
| 561 page_space_(page_space), | 563 page_space_(page_space), |
| 562 marking_stack_(marking_stack), | 564 marking_stack_(marking_stack), |
| 563 delay_set_(delay_set), | 565 delay_set_(delay_set), |
| 566 barrier_(barrier), |
| 564 collect_code_(collect_code), | 567 collect_code_(collect_code), |
| 565 visit_prologue_weak_persistent_handles_( | 568 visit_prologue_weak_persistent_handles_( |
| 566 visit_prologue_weak_persistent_handles) { | 569 visit_prologue_weak_persistent_handles) { |
| 567 } | 570 } |
| 568 | 571 |
| 569 virtual void Run() { | 572 virtual void Run() { |
| 570 Thread::EnterIsolateAsHelper(isolate_, true); | 573 Thread::EnterIsolateAsHelper(isolate_, true); |
| 571 { | 574 { |
| 572 StackZone stack_zone(Thread::Current()); | 575 StackZone stack_zone(Thread::Current()); |
| 573 Zone* zone = stack_zone.GetZone(); | 576 Zone* zone = stack_zone.GetZone(); |
| 574 SkippedCodeFunctions* skipped_code_functions = | 577 SkippedCodeFunctions* skipped_code_functions = |
| 575 collect_code_ ? new(zone) SkippedCodeFunctions() : NULL; | 578 collect_code_ ? new(zone) SkippedCodeFunctions() : NULL; |
| 576 MarkingVisitor visitor(isolate_, heap_, page_space_, marking_stack_, | 579 MarkingVisitor visitor(isolate_, heap_, page_space_, marking_stack_, |
| 577 delay_set_, skipped_code_functions); | 580 delay_set_, skipped_code_functions); |
| 578 // Phase 1: Populate and drain marking stack in task. | 581 // Phase 1: Populate and drain marking stack in task. |
| 579 // TODO(koda): Split root iteration work among multiple tasks. | 582 // TODO(koda): Split root iteration work among multiple tasks. |
| 580 marker_->IterateRoots(isolate_, &visitor, | 583 marker_->IterateRoots(isolate_, &visitor, |
| 581 visit_prologue_weak_persistent_handles_); | 584 visit_prologue_weak_persistent_handles_); |
| 582 visitor.DrainMarkingStack(); | 585 visitor.DrainMarkingStack(); |
| 583 marker_->TaskSync(); | 586 barrier_->Sync(); |
| 584 // Phase 2: Weak processing and follow-up marking on main thread. | 587 // Phase 2: Weak processing and follow-up marking on main thread. |
| 585 marker_->TaskSync(); | 588 barrier_->Sync(); |
| 586 // Phase 3: Finalize results from all markers (detach code, etc.). | 589 // Phase 3: Finalize results from all markers (detach code, etc.). |
| 587 marker_->FinalizeResultsFrom(&visitor); | 590 marker_->FinalizeResultsFrom(&visitor); |
| 588 } | 591 } |
| 589 Thread::ExitIsolateAsHelper(true); | 592 Thread::ExitIsolateAsHelper(true); |
| 590 // This task is done. Notify the original thread. | 593 // This task is done. Notify the original thread. |
| 591 marker_->TaskNotifyDone(); | 594 barrier_->Exit(); |
| 592 } | 595 } |
| 593 | 596 |
| 594 private: | 597 private: |
| 595 GCMarker* marker_; | 598 GCMarker* marker_; |
| 596 Isolate* isolate_; | 599 Isolate* isolate_; |
| 597 Heap* heap_; | 600 Heap* heap_; |
| 598 PageSpace* page_space_; | 601 PageSpace* page_space_; |
| 599 MarkingStack* marking_stack_; | 602 MarkingStack* marking_stack_; |
| 600 DelaySet* delay_set_; | 603 DelaySet* delay_set_; |
| 604 ThreadBarrier* barrier_; |
| 601 bool collect_code_; | 605 bool collect_code_; |
| 602 bool visit_prologue_weak_persistent_handles_; | 606 bool visit_prologue_weak_persistent_handles_; |
| 603 | 607 |
| 604 DISALLOW_COPY_AND_ASSIGN(MarkTask); | 608 DISALLOW_COPY_AND_ASSIGN(MarkTask); |
| 605 }; | 609 }; |
| 606 | 610 |
| 607 | 611 |
| 608 void GCMarker::MainSync(intptr_t num_tasks) { | |
| 609 MonitorLocker ml(&monitor_); | |
| 610 while (done_count_ < num_tasks) { | |
| 611 ml.Wait(); | |
| 612 } | |
| 613 done_count_ = 0; // Tasks may now resume. | |
| 614 // TODO(koda): Add barrier utility with two condition variables to allow for | |
| 615 // Notify rather than NotifyAll. Also use it for safepoints. | |
| 616 ml.NotifyAll(); | |
| 617 } | |
| 618 | |
| 619 | |
| 620 void GCMarker::TaskNotifyDone() { | |
| 621 MonitorLocker ml(&monitor_); | |
| 622 ++done_count_; | |
| 623 // TODO(koda): Add barrier utility with two condition variables to allow for | |
| 624 // Notify rather than NotifyAll. Also use it for safepoints. | |
| 625 ml.NotifyAll(); | |
| 626 } | |
| 627 | |
| 628 | |
| 629 void GCMarker::TaskSync() { | |
| 630 MonitorLocker ml(&monitor_); | |
| 631 ++done_count_; | |
| 632 ml.NotifyAll(); // Notify controller that this thread reached end of phase. | |
| 633 ASSERT(done_count_ > 0); | |
| 634 while (done_count_ > 0) { | |
| 635 // Wait for the controller to release into next phase. | |
| 636 ml.Wait(); | |
| 637 } | |
| 638 } | |
| 639 | |
| 640 | |
| 641 void GCMarker::FinalizeResultsFrom(MarkingVisitor* visitor) { | 612 void GCMarker::FinalizeResultsFrom(MarkingVisitor* visitor) { |
| 642 { | 613 { |
| 643 MonitorLocker ml(&monitor_); | 614 MonitorLocker ml(&monitor_); |
| 644 marked_bytes_ += visitor->marked_bytes(); | 615 marked_bytes_ += visitor->marked_bytes(); |
| 645 } | 616 } |
| 646 visitor->Finalize(); | 617 visitor->Finalize(); |
| 647 } | 618 } |
| 648 | 619 |
| 649 | 620 |
| 650 void GCMarker::MarkObjects(Isolate* isolate, | 621 void GCMarker::MarkObjects(Isolate* isolate, |
| (...skipping 25 matching lines...) Expand all Loading... |
| 676 !visit_prologue_weak_persistent_handles); | 647 !visit_prologue_weak_persistent_handles); |
| 677 // All marking done; detach code, etc. | 648 // All marking done; detach code, etc. |
| 678 FinalizeResultsFrom(&mark); | 649 FinalizeResultsFrom(&mark); |
| 679 } else { | 650 } else { |
| 680 if (num_tasks > 1) { | 651 if (num_tasks > 1) { |
| 681 // TODO(koda): Support multiple: | 652 // TODO(koda): Support multiple: |
| 682 // 1. non-concurrent tasks, after splitting root iteration work, then | 653 // 1. non-concurrent tasks, after splitting root iteration work, then |
| 683 // 2. concurrent tasks, after synchronizing headers. | 654 // 2. concurrent tasks, after synchronizing headers. |
| 684 FATAL("Multiple marking tasks not yet supported"); | 655 FATAL("Multiple marking tasks not yet supported"); |
| 685 } | 656 } |
| 657 ThreadBarrier barrier(num_tasks + 1); // +1 for the main thread. |
| 686 // Phase 1: Populate and drain marking stack in task. | 658 // Phase 1: Populate and drain marking stack in task. |
| 687 MarkTask* mark_task = | 659 MarkTask* mark_task = |
| 688 new MarkTask(this, isolate, heap_, page_space, &marking_stack, | 660 new MarkTask(this, isolate, heap_, page_space, &marking_stack, |
| 689 &delay_set, collect_code, | 661 &delay_set, &barrier, collect_code, |
| 690 visit_prologue_weak_persistent_handles); | 662 visit_prologue_weak_persistent_handles); |
| 691 ThreadPool* pool = Dart::thread_pool(); | 663 ThreadPool* pool = Dart::thread_pool(); |
| 692 pool->Run(mark_task); | 664 pool->Run(mark_task); |
| 693 MainSync(num_tasks); | 665 barrier.Sync(); |
| 694 // Phase 2: Weak processing and follow-up marking on main thread. | 666 // Phase 2: Weak processing and follow-up marking on main thread. |
| 695 SkippedCodeFunctions* skipped_code_functions = | 667 SkippedCodeFunctions* skipped_code_functions = |
| 696 collect_code ? new(zone) SkippedCodeFunctions() : NULL; | 668 collect_code ? new(zone) SkippedCodeFunctions() : NULL; |
| 697 MarkingVisitor mark(isolate, heap_, page_space, &marking_stack, | 669 MarkingVisitor mark(isolate, heap_, page_space, &marking_stack, |
| 698 &delay_set, skipped_code_functions); | 670 &delay_set, skipped_code_functions); |
| 699 IterateWeakReferences(isolate, &mark); | 671 IterateWeakReferences(isolate, &mark); |
| 700 MarkingWeakVisitor mark_weak; | 672 MarkingWeakVisitor mark_weak; |
| 701 IterateWeakRoots(isolate, &mark_weak, | 673 IterateWeakRoots(isolate, &mark_weak, |
| 702 !visit_prologue_weak_persistent_handles); | 674 !visit_prologue_weak_persistent_handles); |
| 703 MainSync(num_tasks); | 675 barrier.Sync(); |
| 704 // Phase 3: Finalize results from all markers (detach code, etc.). | 676 // Phase 3: Finalize results from all markers (detach code, etc.). |
| 705 FinalizeResultsFrom(&mark); | 677 FinalizeResultsFrom(&mark); |
| 706 MainSync(num_tasks); | 678 barrier.Exit(); |
| 707 // Finalization complete and all tasks exited. | |
| 708 } | 679 } |
| 709 delay_set.ClearReferences(); | 680 delay_set.ClearReferences(); |
| 710 ProcessWeakTables(page_space); | 681 ProcessWeakTables(page_space); |
| 711 ProcessObjectIdTable(isolate); | 682 ProcessObjectIdTable(isolate); |
| 712 } | 683 } |
| 713 Epilogue(isolate, invoke_api_callbacks); | 684 Epilogue(isolate, invoke_api_callbacks); |
| 714 } | 685 } |
| 715 | 686 |
| 716 } // namespace dart | 687 } // namespace dart |
| OLD | NEW |