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 |