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

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: Highlight corresponding phases; finalize results in parallel. 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);
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)
Ivan Posva 2015/08/28 05:23:22 ditto. see below
koda 2015/08/28 13:27:54 Done.
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 // Phase 1: Populate and drain marking stack in task.
578 // TODO(koda): Split root iteration work among multiple tasks.
579 GCMarker::IterateRoots(isolate_, &visitor, !invoke_api_callbacks_);
580 visitor.DrainMarkingStack();
581 marker_->TaskSync();
582 // Phase 2: Weak processing and follow-up marking on main thread.
583 marker_->TaskSync();
584 // Phase 3: Finalize results from all markers (detach code, etc.).
585 marker_->FinalizeResultsFrom(&visitor);
586 }
587 Thread::ExitIsolateAsHelper(true);
588 // This task is done. Notify the original thread.
589 marker_->TaskNotifyDone();
590 }
591
592 private:
593 GCMarker* marker_;
594 Isolate* isolate_;
595 Heap* heap_;
596 PageSpace* page_space_;
597 MarkingStack* marking_stack_;
598 DelaySet* delay_set_;
599 bool collect_code_;
600 bool invoke_api_callbacks_;
601
602 DISALLOW_COPY_AND_ASSIGN(MarkTask);
603 };
604
605
606 void GCMarker::MainSync(intptr_t num_tasks) {
607 MonitorLocker ml(&monitor_);
608 while (done_count_ < num_tasks) {
609 ml.Wait();
610 }
611 done_count_ = 0; // Tasks may now resume.
612 // TODO(koda): Add barrier utility with two condition variables to allow for
613 // Notify rather than NotifyAll. Also use it for safepoints.
614 ml.NotifyAll();
615 }
616
617
618 void GCMarker::TaskNotifyDone() {
619 MonitorLocker ml(&monitor_);
620 ++done_count_;
621 // TODO(koda): Add barrier utility with two condition variables to allow for
622 // Notify rather than NotifyAll. Also use it for safepoints.
623 ml.NotifyAll();
624 }
625
626
627 void GCMarker::TaskSync() {
628 TaskNotifyDone();
629 MonitorLocker ml(&monitor_);
Ivan Posva 2015/08/28 05:23:23 At the expense of duplicated code, but it has two
koda 2015/08/28 13:27:54 Done.
630 while (done_count_ > 0) {
631 ml.Wait();
632 }
633 }
634
635
636 void GCMarker::FinalizeResultsFrom(MarkingVisitor* visitor) {
637 {
638 MonitorLocker ml(&monitor_);
639 marked_bytes_ += visitor->marked_bytes();
640 }
641 visitor->Finalize();
642 }
643
644
544 void GCMarker::MarkObjects(Isolate* isolate, 645 void GCMarker::MarkObjects(Isolate* isolate,
545 PageSpace* page_space, 646 PageSpace* page_space,
546 bool invoke_api_callbacks, 647 bool invoke_api_callbacks,
547 bool collect_code) { 648 bool collect_code) {
548 Prologue(isolate, invoke_api_callbacks); 649 Prologue(isolate, invoke_api_callbacks);
549 // The API prologue/epilogue may create/destroy zones, so we must not 650 // The API prologue/epilogue may create/destroy zones, so we must not
550 // depend on zone allocations surviving beyond the epilogue callback. 651 // depend on zone allocations surviving beyond the epilogue callback.
551 { 652 {
552 StackZone stack_zone(Thread::Current()); 653 StackZone stack_zone(Thread::Current());
553 Zone* zone = stack_zone.GetZone(); 654 Zone* zone = stack_zone.GetZone();
554 MarkingStack marking_stack; 655 MarkingStack marking_stack;
555 DelaySet delay_set; 656 DelaySet delay_set;
556 SkippedCodeFunctions* skipped_code_functions = 657 marked_bytes_ = 0;
557 collect_code ? new(zone) SkippedCodeFunctions() : NULL; 658 const int num_tasks = FLAG_marker_tasks;
558 MarkingVisitor mark(isolate, heap_, page_space, &marking_stack, 659 if (num_tasks == 0) {
559 &delay_set, skipped_code_functions); 660 // Mark everything on main thread.
560 IterateRoots(isolate, &mark, !invoke_api_callbacks); 661 SkippedCodeFunctions* skipped_code_functions =
561 mark.DrainMarkingStack(); 662 collect_code ? new(zone) SkippedCodeFunctions() : NULL;
562 IterateWeakReferences(isolate, &mark); 663 MarkingVisitor mark(isolate, heap_, page_space, &marking_stack,
563 MarkingWeakVisitor mark_weak; 664 &delay_set, skipped_code_functions);
564 IterateWeakRoots(isolate, &mark_weak, invoke_api_callbacks); 665 IterateRoots(isolate, &mark, !invoke_api_callbacks);
565 // TODO(koda): Add hand-over callback. 666 mark.DrainMarkingStack();
566 marked_bytes_ = mark.marked_bytes(); 667 IterateWeakReferences(isolate, &mark);
567 mark.Finalize(); 668 MarkingWeakVisitor mark_weak;
669 IterateWeakRoots(isolate, &mark_weak, invoke_api_callbacks);
670 // All marking done; detach code, etc.
671 FinalizeResultsFrom(&mark);
672 } else {
673 if (num_tasks > 1) {
674 // TODO(koda): Support multiple:
675 // 1. non-concurrent tasks, after splitting root iteration work, then
676 // 2. concurrent tasks, after synchronizing headers.
677 FATAL("Multiple marking tasks not yet supported");
678 }
679 // Phase 1: Populate and drain marking stack in task.
Ivan Posva 2015/08/28 05:23:22 How about: bool visit_prologue_weak_persistent_ha
koda 2015/08/28 13:27:54 Done. Also updated the existing code in the num_ta
680 MarkTask* mark_task =
681 new MarkTask(this, isolate, heap_, page_space, &marking_stack,
682 &delay_set, collect_code, invoke_api_callbacks);
683 ThreadPool* pool = Dart::thread_pool();
684 pool->Run(mark_task);
685 MainSync(num_tasks);
686 // Phase 2: Weak processing and follow-up marking 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);
Ivan Posva 2015/08/28 05:23:22 And here use !visit_prologue_weak_persistent_handl
koda 2015/08/28 13:27:54 Done.
694 MainSync(num_tasks);
695 // Phase 3: Finalize results from all markers (detach code, etc.).
696 FinalizeResultsFrom(&mark);
697 MainSync(num_tasks);
698 // Finalization complete and all tasks exited.
699 }
568 delay_set.ClearReferences(); 700 delay_set.ClearReferences();
569 ProcessWeakTables(page_space); 701 ProcessWeakTables(page_space);
570 ProcessObjectIdTable(isolate); 702 ProcessObjectIdTable(isolate);
571 } 703 }
572 Epilogue(isolate, invoke_api_callbacks); 704 Epilogue(isolate, invoke_api_callbacks);
573 } 705 }
574 706
575 } // namespace dart 707 } // 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