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

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

Issue 1309033007: Old-gen marking on separate thread (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Ready for review. Created 5 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
« no previous file with comments | « runtime/vm/gc_marker.h ('k') | runtime/vm/thread.h » ('j') | 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) 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_pool.h" 19 #include "vm/thread_pool.h"
20 #include "vm/visitor.h" 20 #include "vm/visitor.h"
21 #include "vm/object_id_ring.h" 21 #include "vm/object_id_ring.h"
22 22
23 namespace dart { 23 namespace dart {
24 24
25 DEFINE_FLAG(int, marker_tasks, 1,
26 "The number of tasks to spawn during old gen GC marking (0 means "
27 "perform all marking on main thread).");
28
25 typedef StoreBufferBlock PointerBlock; // TODO(koda): Rename to PointerBlock. 29 typedef StoreBufferBlock PointerBlock; // TODO(koda): Rename to PointerBlock.
26 typedef StoreBuffer MarkingStack; // TODO(koda): Create shared base class. 30 typedef StoreBuffer MarkingStack; // TODO(koda): Create shared base class.
27 31
28 class DelaySet { 32 class DelaySet {
29 private: 33 private:
30 typedef std::multimap<RawObject*, RawWeakProperty*> Map; 34 typedef std::multimap<RawObject*, RawWeakProperty*> Map;
31 typedef std::pair<RawObject*, RawWeakProperty*> MapEntry; 35 typedef std::pair<RawObject*, RawWeakProperty*> MapEntry;
32 36
33 public: 37 public:
34 DelaySet() : mutex_(new Mutex()) {} 38 DelaySet() : mutex_(new Mutex()) {}
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after
414 } 418 }
415 } 419 }
416 420
417 421
418 void GCMarker::IterateRoots(Isolate* isolate, 422 void GCMarker::IterateRoots(Isolate* isolate,
419 ObjectPointerVisitor* visitor, 423 ObjectPointerVisitor* visitor,
420 bool visit_prologue_weak_persistent_handles) { 424 bool visit_prologue_weak_persistent_handles) {
421 isolate->VisitObjectPointers(visitor, 425 isolate->VisitObjectPointers(visitor,
422 visit_prologue_weak_persistent_handles, 426 visit_prologue_weak_persistent_handles,
423 StackFrameIterator::kDontValidateFrames); 427 StackFrameIterator::kDontValidateFrames);
424 heap_->new_space()->VisitObjectPointers(visitor); 428 isolate->heap()->new_space()->VisitObjectPointers(visitor);
Ivan Posva 2015/08/28 05:23:22 The GCMarker still has a heap_ reference, why has
koda 2015/08/28 13:27:53 Because I made this method static, since it doesn'
425 } 429 }
426 430
427 431
428 void GCMarker::IterateWeakRoots(Isolate* isolate, 432 void GCMarker::IterateWeakRoots(Isolate* isolate,
429 HandleVisitor* visitor, 433 HandleVisitor* visitor,
430 bool visit_prologue_weak_persistent_handles) { 434 bool visit_prologue_weak_persistent_handles) {
431 ApiState* state = isolate->api_state(); 435 ApiState* state = isolate->api_state();
432 ASSERT(state != NULL); 436 ASSERT(state != NULL);
433 isolate->VisitWeakPersistentHandles(visitor, 437 isolate->VisitWeakPersistentHandles(visitor,
434 visit_prologue_weak_persistent_handles); 438 visit_prologue_weak_persistent_handles);
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
534 538
535 539
536 void GCMarker::ProcessObjectIdTable(Isolate* isolate) { 540 void GCMarker::ProcessObjectIdTable(Isolate* isolate) {
537 ObjectIdRingClearPointerVisitor visitor(isolate); 541 ObjectIdRingClearPointerVisitor visitor(isolate);
538 ObjectIdRing* ring = isolate->object_id_ring(); 542 ObjectIdRing* ring = isolate->object_id_ring();
539 ASSERT(ring != NULL); 543 ASSERT(ring != NULL);
540 ring->VisitPointers(&visitor); 544 ring->VisitPointers(&visitor);
541 } 545 }
542 546
543 547
548 class MarkTask : public ThreadPool::Task {
549 public:
550 MarkTask(GCMarker* marker,
551 Isolate* isolate,
552 Heap* heap,
553 PageSpace* page_space,
554 MarkingStack* marking_stack,
555 DelaySet* delay_set,
556 bool collect_code,
557 bool invoke_api_callbacks)
558 : marker_(marker),
559 isolate_(isolate),
560 heap_(heap),
561 page_space_(page_space),
562 marking_stack_(marking_stack),
563 delay_set_(delay_set),
564 collect_code_(collect_code),
565 invoke_api_callbacks_(invoke_api_callbacks) {
566 }
567
568 virtual void Run() {
569 Thread::EnterIsolateAsHelper(isolate_, true);
570 {
571 StackZone stack_zone(Thread::Current());
572 Zone* zone = stack_zone.GetZone();
573 SkippedCodeFunctions* skipped_code_functions =
574 collect_code_ ? new(zone) SkippedCodeFunctions() : NULL;
575 MarkingVisitor visitor(isolate_, heap_, page_space_, marking_stack_,
576 delay_set_, skipped_code_functions);
577 // TODO(koda): Split root iteration work among multiple tasks.
578 GCMarker::IterateRoots(isolate_, &visitor, !invoke_api_callbacks_);
579 visitor.DrainMarkingStack();
580 marker_->TaskSync();
581 // Wait for weak processing on main thread...
582 marker_->TaskSync();
583 // All marking done; detach code, etc.
584 marker_->FinalizeResultsFrom(&visitor);
585 }
586 Thread::ExitIsolateAsHelper(true);
587 // This task is done. Notify the original thread.
588 marker_->TaskNotifyDone();
589 }
590
591 private:
592 GCMarker* marker_;
593 Isolate* isolate_;
594 Heap* heap_;
595 PageSpace* page_space_;
596 MarkingStack* marking_stack_;
597 DelaySet* delay_set_;
598 bool collect_code_;
599 bool invoke_api_callbacks_;
600
601 DISALLOW_COPY_AND_ASSIGN(MarkTask);
602 };
603
604
605 void GCMarker::MainSync(intptr_t num_tasks) {
606 MonitorLocker ml(&monitor_);
607 while (done_count_ < num_tasks) {
608 ml.Wait();
609 }
610 done_count_ = 0; // Tasks may now resume.
611 // TODO(koda): Add barrier utility with two condition variables to allow for
612 // Notify rather than NotifyAll. Also use it for safepoints.
613 ml.NotifyAll();
614 }
615
616
617 void GCMarker::TaskNotifyDone() {
618 MonitorLocker ml(&monitor_);
619 ++done_count_;
620 // TODO(koda): Add barrier utility with two condition variables to allow for
621 // Notify rather than NotifyAll. Also use it for safepoints.
622 ml.NotifyAll();
623 }
624
625
626 void GCMarker::TaskSync() {
627 TaskNotifyDone();
628 MonitorLocker ml(&monitor_);
629 while (done_count_ > 0) {
630 ml.Wait();
631 }
632 }
633
634
635 void GCMarker::FinalizeResultsFrom(MarkingVisitor* visitor) {
636 {
637 MonitorLocker ml(&monitor_);
638 marked_bytes_ += visitor->marked_bytes();
639 }
640 visitor->Finalize();
641 }
642
643
544 void GCMarker::MarkObjects(Isolate* isolate, 644 void GCMarker::MarkObjects(Isolate* isolate,
545 PageSpace* page_space, 645 PageSpace* page_space,
546 bool invoke_api_callbacks, 646 bool invoke_api_callbacks,
547 bool collect_code) { 647 bool collect_code) {
548 Prologue(isolate, invoke_api_callbacks); 648 Prologue(isolate, invoke_api_callbacks);
549 // The API prologue/epilogue may create/destroy zones, so we must not 649 // The API prologue/epilogue may create/destroy zones, so we must not
550 // depend on zone allocations surviving beyond the epilogue callback. 650 // depend on zone allocations surviving beyond the epilogue callback.
551 { 651 {
552 StackZone stack_zone(Thread::Current()); 652 StackZone stack_zone(Thread::Current());
553 Zone* zone = stack_zone.GetZone(); 653 Zone* zone = stack_zone.GetZone();
554 MarkingStack marking_stack; 654 MarkingStack marking_stack;
555 DelaySet delay_set; 655 DelaySet delay_set;
556 SkippedCodeFunctions* skipped_code_functions = 656 marked_bytes_ = 0;
557 collect_code ? new(zone) SkippedCodeFunctions() : NULL; 657 const int num_tasks = FLAG_marker_tasks;
558 MarkingVisitor mark(isolate, heap_, page_space, &marking_stack, 658 if (num_tasks == 0) {
559 &delay_set, skipped_code_functions); 659 // Mark everything on main thread.
560 IterateRoots(isolate, &mark, !invoke_api_callbacks); 660 SkippedCodeFunctions* skipped_code_functions =
561 mark.DrainMarkingStack(); 661 collect_code ? new(zone) SkippedCodeFunctions() : NULL;
562 IterateWeakReferences(isolate, &mark); 662 MarkingVisitor mark(isolate, heap_, page_space, &marking_stack,
563 MarkingWeakVisitor mark_weak; 663 &delay_set, skipped_code_functions);
564 IterateWeakRoots(isolate, &mark_weak, invoke_api_callbacks); 664 IterateRoots(isolate, &mark, !invoke_api_callbacks);
565 // TODO(koda): Add hand-over callback. 665 mark.DrainMarkingStack();
566 marked_bytes_ = mark.marked_bytes(); 666 IterateWeakReferences(isolate, &mark);
567 mark.Finalize(); 667 MarkingWeakVisitor mark_weak;
668 IterateWeakRoots(isolate, &mark_weak, invoke_api_callbacks);
669 // All marking done; detach code, etc.
670 FinalizeResultsFrom(&mark);
671 } else {
672 if (num_tasks > 1) {
673 // TODO(koda): Support multiple:
674 // 1. non-concurrent tasks, after splitting root iteration work, then
675 // 2. concurrent tasks, after synchronizing headers.
676 FATAL("Multiple marking tasks not yet supported");
677 }
678 // Spawn a marking task on a separate thread.
679 MarkTask* mark_task =
680 new MarkTask(this, isolate, heap_, page_space, &marking_stack,
681 &delay_set, collect_code, invoke_api_callbacks);
682 ThreadPool* pool = Dart::thread_pool();
683 pool->Run(mark_task);
684 MainSync(num_tasks);
685 {
686 // Perform weak processing on main thread.
687 SkippedCodeFunctions* skipped_code_functions =
688 collect_code ? new(zone) SkippedCodeFunctions() : NULL;
689 MarkingVisitor mark(isolate, heap_, page_space, &marking_stack,
690 &delay_set, skipped_code_functions);
691 IterateWeakReferences(isolate, &mark);
692 MarkingWeakVisitor mark_weak;
693 IterateWeakRoots(isolate, &mark_weak, invoke_api_callbacks);
694 // All marking done; detach code, etc.
695 FinalizeResultsFrom(&mark);
696 }
697 MainSync(num_tasks);
698 // Wait for mark task finalization...
699 MainSync(num_tasks);
700 }
568 delay_set.ClearReferences(); 701 delay_set.ClearReferences();
569 ProcessWeakTables(page_space); 702 ProcessWeakTables(page_space);
570 ProcessObjectIdTable(isolate); 703 ProcessObjectIdTable(isolate);
571 } 704 }
572 Epilogue(isolate, invoke_api_callbacks); 705 Epilogue(isolate, invoke_api_callbacks);
573 } 706 }
574 707
575 } // namespace dart 708 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/gc_marker.h ('k') | runtime/vm/thread.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698