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

Unified 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, 4 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/gc_marker.h ('k') | runtime/vm/thread.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/gc_marker.cc
diff --git a/runtime/vm/gc_marker.cc b/runtime/vm/gc_marker.cc
index 4ad7e8f1ddc586ac1859384b955fbc710a37f005..426121dd27e3b12b2d788f3debf52cdee841a5b1 100644
--- a/runtime/vm/gc_marker.cc
+++ b/runtime/vm/gc_marker.cc
@@ -22,6 +22,10 @@
namespace dart {
+DEFINE_FLAG(int, marker_tasks, 1,
+ "The number of tasks to spawn during old gen GC marking (0 means "
+ "perform all marking on main thread).");
+
typedef StoreBufferBlock PointerBlock; // TODO(koda): Rename to PointerBlock.
typedef StoreBuffer MarkingStack; // TODO(koda): Create shared base class.
@@ -421,7 +425,7 @@ void GCMarker::IterateRoots(Isolate* isolate,
isolate->VisitObjectPointers(visitor,
visit_prologue_weak_persistent_handles,
StackFrameIterator::kDontValidateFrames);
- heap_->new_space()->VisitObjectPointers(visitor);
+ 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'
}
@@ -541,6 +545,102 @@ void GCMarker::ProcessObjectIdTable(Isolate* isolate) {
}
+class MarkTask : public ThreadPool::Task {
+ public:
+ MarkTask(GCMarker* marker,
+ Isolate* isolate,
+ Heap* heap,
+ PageSpace* page_space,
+ MarkingStack* marking_stack,
+ DelaySet* delay_set,
+ bool collect_code,
+ bool invoke_api_callbacks)
+ : marker_(marker),
+ isolate_(isolate),
+ heap_(heap),
+ page_space_(page_space),
+ marking_stack_(marking_stack),
+ delay_set_(delay_set),
+ collect_code_(collect_code),
+ invoke_api_callbacks_(invoke_api_callbacks) {
+ }
+
+ virtual void Run() {
+ Thread::EnterIsolateAsHelper(isolate_, true);
+ {
+ StackZone stack_zone(Thread::Current());
+ Zone* zone = stack_zone.GetZone();
+ SkippedCodeFunctions* skipped_code_functions =
+ collect_code_ ? new(zone) SkippedCodeFunctions() : NULL;
+ MarkingVisitor visitor(isolate_, heap_, page_space_, marking_stack_,
+ delay_set_, skipped_code_functions);
+ // TODO(koda): Split root iteration work among multiple tasks.
+ GCMarker::IterateRoots(isolate_, &visitor, !invoke_api_callbacks_);
+ visitor.DrainMarkingStack();
+ marker_->TaskSync();
+ // Wait for weak processing on main thread...
+ marker_->TaskSync();
+ // All marking done; detach code, etc.
+ marker_->FinalizeResultsFrom(&visitor);
+ }
+ Thread::ExitIsolateAsHelper(true);
+ // This task is done. Notify the original thread.
+ marker_->TaskNotifyDone();
+ }
+
+ private:
+ GCMarker* marker_;
+ Isolate* isolate_;
+ Heap* heap_;
+ PageSpace* page_space_;
+ MarkingStack* marking_stack_;
+ DelaySet* delay_set_;
+ bool collect_code_;
+ bool invoke_api_callbacks_;
+
+ DISALLOW_COPY_AND_ASSIGN(MarkTask);
+};
+
+
+void GCMarker::MainSync(intptr_t num_tasks) {
+ MonitorLocker ml(&monitor_);
+ while (done_count_ < num_tasks) {
+ ml.Wait();
+ }
+ done_count_ = 0; // Tasks may now resume.
+ // TODO(koda): Add barrier utility with two condition variables to allow for
+ // Notify rather than NotifyAll. Also use it for safepoints.
+ ml.NotifyAll();
+}
+
+
+void GCMarker::TaskNotifyDone() {
+ MonitorLocker ml(&monitor_);
+ ++done_count_;
+ // TODO(koda): Add barrier utility with two condition variables to allow for
+ // Notify rather than NotifyAll. Also use it for safepoints.
+ ml.NotifyAll();
+}
+
+
+void GCMarker::TaskSync() {
+ TaskNotifyDone();
+ MonitorLocker ml(&monitor_);
+ while (done_count_ > 0) {
+ ml.Wait();
+ }
+}
+
+
+void GCMarker::FinalizeResultsFrom(MarkingVisitor* visitor) {
+ {
+ MonitorLocker ml(&monitor_);
+ marked_bytes_ += visitor->marked_bytes();
+ }
+ visitor->Finalize();
+}
+
+
void GCMarker::MarkObjects(Isolate* isolate,
PageSpace* page_space,
bool invoke_api_callbacks,
@@ -553,18 +653,51 @@ void GCMarker::MarkObjects(Isolate* isolate,
Zone* zone = stack_zone.GetZone();
MarkingStack marking_stack;
DelaySet delay_set;
- SkippedCodeFunctions* skipped_code_functions =
- collect_code ? new(zone) SkippedCodeFunctions() : NULL;
- MarkingVisitor mark(isolate, heap_, page_space, &marking_stack,
- &delay_set, skipped_code_functions);
- IterateRoots(isolate, &mark, !invoke_api_callbacks);
- mark.DrainMarkingStack();
- IterateWeakReferences(isolate, &mark);
- MarkingWeakVisitor mark_weak;
- IterateWeakRoots(isolate, &mark_weak, invoke_api_callbacks);
- // TODO(koda): Add hand-over callback.
- marked_bytes_ = mark.marked_bytes();
- mark.Finalize();
+ marked_bytes_ = 0;
+ const int num_tasks = FLAG_marker_tasks;
+ if (num_tasks == 0) {
+ // Mark everything on main thread.
+ SkippedCodeFunctions* skipped_code_functions =
+ collect_code ? new(zone) SkippedCodeFunctions() : NULL;
+ MarkingVisitor mark(isolate, heap_, page_space, &marking_stack,
+ &delay_set, skipped_code_functions);
+ IterateRoots(isolate, &mark, !invoke_api_callbacks);
+ mark.DrainMarkingStack();
+ IterateWeakReferences(isolate, &mark);
+ MarkingWeakVisitor mark_weak;
+ IterateWeakRoots(isolate, &mark_weak, invoke_api_callbacks);
+ // All marking done; detach code, etc.
+ FinalizeResultsFrom(&mark);
+ } else {
+ if (num_tasks > 1) {
+ // TODO(koda): Support multiple:
+ // 1. non-concurrent tasks, after splitting root iteration work, then
+ // 2. concurrent tasks, after synchronizing headers.
+ FATAL("Multiple marking tasks not yet supported");
+ }
+ // Spawn a marking task on a separate thread.
+ MarkTask* mark_task =
+ new MarkTask(this, isolate, heap_, page_space, &marking_stack,
+ &delay_set, collect_code, invoke_api_callbacks);
+ ThreadPool* pool = Dart::thread_pool();
+ pool->Run(mark_task);
+ MainSync(num_tasks);
+ {
+ // Perform weak processing on main thread.
+ SkippedCodeFunctions* skipped_code_functions =
+ collect_code ? new(zone) SkippedCodeFunctions() : NULL;
+ MarkingVisitor mark(isolate, heap_, page_space, &marking_stack,
+ &delay_set, skipped_code_functions);
+ IterateWeakReferences(isolate, &mark);
+ MarkingWeakVisitor mark_weak;
+ IterateWeakRoots(isolate, &mark_weak, invoke_api_callbacks);
+ // All marking done; detach code, etc.
+ FinalizeResultsFrom(&mark);
+ }
+ MainSync(num_tasks);
+ // Wait for mark task finalization...
+ MainSync(num_tasks);
+ }
delay_set.ClearReferences();
ProcessWeakTables(page_space);
ProcessObjectIdTable(isolate);
« 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