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

Unified Diff: runtime/vm/gc_marker.cc

Issue 2041413005: VM: Fix WeakProperty processing during parallel marking. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: restore assertion in the right place Created 4 years, 6 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/platform/assert.h ('k') | no next file » | 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 069f34175990a492b4c75280f2062e1e58ad0153..5004920b71cb1dd6a43beca1a9674a0de79fc410 100644
--- a/runtime/vm/gc_marker.cc
+++ b/runtime/vm/gc_marker.cc
@@ -177,12 +177,43 @@ class MarkingVisitorBase : public ObjectPointerVisitor {
return class_stats_size_[class_id];
}
- // Returns true if some non-zero amount of work was performed.
- bool DrainMarkingStack() {
+ bool ProcessPendingWeakProperties() {
+ bool marked = false;
+ RawWeakProperty* cur_weak = delayed_weak_properties_;
+ delayed_weak_properties_ = NULL;
+ while (cur_weak != NULL) {
+ uword next_weak = cur_weak->ptr()->next_;
+ RawObject* raw_key = cur_weak->ptr()->key_;
+ // Reset the next pointer in the weak property.
+ cur_weak->ptr()->next_ = 0;
+ if (raw_key->IsMarked()) {
+ RawObject* raw_val = cur_weak->ptr()->value_;
+ marked = marked || (raw_val->IsHeapObject() && !raw_val->IsMarked());
+
+ // The key is marked so we make sure to properly visit all pointers
+ // originating from this weak property.
+ VisitingOldObject(cur_weak);
+ cur_weak->VisitPointers(this);
+ } else {
+ // Requeue this weak property to be handled later.
+ EnqueueWeakProperty(cur_weak);
+ }
+ // Advance to next weak property in the queue.
+ cur_weak = reinterpret_cast<RawWeakProperty*>(next_weak);
+ }
+
+ return marked;
+ }
+
+ void DrainMarkingStack() {
RawObject* raw_obj = work_list_.Pop();
+ if ((raw_obj == NULL) && ProcessPendingWeakProperties()) {
+ raw_obj = work_list_.Pop();
+ }
+
if (raw_obj == NULL) {
ASSERT(visiting_old_object_ == NULL);
- return false;
+ return;
}
do {
do {
@@ -200,33 +231,13 @@ class MarkingVisitorBase : public ObjectPointerVisitor {
} while (raw_obj != NULL);
// Marking stack is empty.
- // Process all the pending weak properties in this visitor.
- RawWeakProperty* cur_weak = delayed_weak_properties_;
- delayed_weak_properties_ = NULL;
- while (cur_weak != NULL) {
- uword next_weak = cur_weak->ptr()->next_;
- RawObject* raw_key = cur_weak->ptr()->key_;
- // Reset the next pointer in the weak property.
- cur_weak->ptr()->next_ = 0;
- if (raw_key->IsMarked()) {
- // The key is marked so we make sure to properly visit all pointers
- // originating from this weak property.
- VisitingOldObject(cur_weak);
- cur_weak->VisitPointers(this);
- } else {
- // Requeue this weak property to be handled later.
- EnqueueWeakProperty(cur_weak);
- }
- // Advance to next weak property in the queue.
- cur_weak = reinterpret_cast<RawWeakProperty*>(next_weak);
- }
+ ProcessPendingWeakProperties();
// Check whether any further work was pushed either by other markers or
// by the handling of weak properties.
raw_obj = work_list_.Pop();
} while (raw_obj != NULL);
VisitingOldObject(NULL);
- return true;
}
void VisitPointers(RawObject** first, RawObject** last) {
@@ -282,6 +293,7 @@ class MarkingVisitorBase : public ObjectPointerVisitor {
while (cur_weak != NULL) {
uword next_weak = cur_weak->ptr()->next_;
cur_weak->ptr()->next_ = 0;
+ RELEASE_ASSERT(!cur_weak->ptr()->key_->IsMarked());
WeakProperty::Clear(cur_weak);
weak_properties_cleared++;
// Advance to next weak property in the queue.
@@ -569,28 +581,54 @@ class MarkTask : public ThreadPool::Task {
skipped_code_functions);
// Phase 1: Iterate over roots and drain marking stack in tasks.
marker_->IterateRoots(isolate_, &visitor, task_index_, num_tasks_);
- do {
- visitor.DrainMarkingStack();
- // I can't find more work right now. If no other task is busy,
- // then there will never be more work (NB: 1 is *before* decrement).
- if (AtomicOperations::FetchAndDecrement(num_busy_) == 1) break;
-
- // Wait for some work to appear.
- // TODO(iposva): Replace busy-waiting with a solution using Monitor,
- // and redraw the boundaries between stack/visitor/task as needed.
- while (marking_stack_->IsEmpty() &&
- AtomicOperations::LoadRelaxed(num_busy_) > 0) {
+ bool more_to_mark = false;
+ do {
+ do {
+ visitor.DrainMarkingStack();
+
+ // I can't find more work right now. If no other task is busy,
+ // then there will never be more work (NB: 1 is *before* decrement).
+ if (AtomicOperations::FetchAndDecrement(num_busy_) == 1) break;
+
+ // Wait for some work to appear.
+ // TODO(iposva): Replace busy-waiting with a solution using Monitor,
+ // and redraw the boundaries between stack/visitor/task as needed.
+ while (marking_stack_->IsEmpty() &&
+ AtomicOperations::LoadRelaxed(num_busy_) > 0) {
+ }
+
+ // If no tasks are busy, there will never be more work.
+ if (AtomicOperations::LoadRelaxed(num_busy_) == 0) break;
+
+ // I saw some work; get busy and compete for it.
+ AtomicOperations::FetchAndIncrement(num_busy_);
+ } while (true);
+ // Wait for all markers to stop.
+ barrier_->Sync();
+ ASSERT(AtomicOperations::LoadRelaxed(num_busy_) == 0);
+
+ // Check if we have any pending properties with marked keys.
+ // Those might have been marked by another marker.
+ more_to_mark = visitor.ProcessPendingWeakProperties();
+ if (more_to_mark) {
+ // We have more work to do. Notify others.
+ AtomicOperations::FetchAndIncrement(num_busy_);
}
- // If no tasks are busy, there will never be more work.
- if (AtomicOperations::LoadRelaxed(num_busy_) == 0) break;
-
- // I saw some work; get busy and compete for it.
- AtomicOperations::FetchAndIncrement(num_busy_);
- } while (true);
- ASSERT(AtomicOperations::LoadRelaxed(num_busy_) == 0);
- barrier_->Sync();
+ // Wait for all other markers to finish processing their pending
+ // weak properties and decide if they need to continue marking.
+ // Caveat: we need two barriers here to make this decision in lock step
+ // between all markers and the main thread.
+ barrier_->Sync();
+ if (!more_to_mark && (AtomicOperations::LoadRelaxed(num_busy_) > 0)) {
+ // All markers continue to marker as long as any single marker has
+ // some work to do.
+ AtomicOperations::FetchAndIncrement(num_busy_);
+ more_to_mark = true;
+ }
+ barrier_->Sync();
siva 2016/06/08 19:45:20 Why is this barrier_->Sync() necessary? At this po
Vyacheslav Egorov (Google) 2016/06/09 08:17:05 Because strictly speaking one thread that has work
siva 2016/06/09 16:39:53 True if we let the threads run we get into a scena
+ } while (more_to_mark);
// Phase 2: Weak processing and follow-up marking on main thread.
barrier_->Sync();
@@ -688,7 +726,19 @@ void GCMarker::MarkObjects(Isolate* isolate,
ThreadPool* pool = Dart::thread_pool();
pool->Run(mark_task);
}
- barrier.Sync();
+ bool more_to_mark = false;
+ do {
+ // Wait for all markers to stop.
+ barrier.Sync();
+
+ // Wait for all markers to go through weak properties and verify
+ // that there are no more objects to mark.
+ // Note: we need to have two barriers here because we want all markers
+ // and main thread to make decisions in lock step.
+ barrier.Sync();
siva 2016/06/08 19:45:20 back to back barrier.Sync() calls with no code bet
Vyacheslav Egorov (Google) 2016/06/09 08:17:06 These barriers correspond to barriers in the marke
siva 2016/06/09 16:39:53 Acknowledged.
+ more_to_mark = AtomicOperations::LoadRelaxed(&num_busy) > 0;
+ barrier.Sync();
+ } while (more_to_mark);
siva 2016/06/08 19:45:20 Is this loop necessary could we just assert after
Vyacheslav Egorov (Google) 2016/06/09 08:17:05 Yes, the loop is necessary, because there is a loo
siva 2016/06/09 16:39:53 Acknowledged.
// Phase 2: Weak processing on main thread.
{
« no previous file with comments | « runtime/platform/assert.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698