Always mark reference referents in transaction mode.
Fix a to-space invariant check failure in EnqueueFinalizerReferences.
Reference processing can be a problem and useless during transaction
because it's not easy to roll back what reference processing does and
there's no daemon threads running (in the unstarted runtime). To avoid
issues, always mark reference referents.
Add a do_atomic_update parameter to MarkHeapReference.
Bug: 35417063
Test: test-art-host with CC/CMS/SS.
Change-Id: If32eba8fca19ef86e5d13f7925d179c8aecb9e27
diff --git a/runtime/gc/reference_queue.cc b/runtime/gc/reference_queue.cc
index 734caea..fd5dcf9 100644
--- a/runtime/gc/reference_queue.cc
+++ b/runtime/gc/reference_queue.cc
@@ -67,6 +67,11 @@
list_->SetPendingNext(next);
}
ref->SetPendingNext(nullptr);
+ return ref;
+}
+
+// This must be called whenever DequeuePendingReference is called.
+void ReferenceQueue::DisableReadBarrierForReference(ObjPtr<mirror::Reference> ref) {
Heap* heap = Runtime::Current()->GetHeap();
if (kUseBakerOrBrooksReadBarrier && heap->CurrentCollectorType() == kCollectorTypeCC &&
heap->ConcurrentCopyingCollector()->IsActive()) {
@@ -92,7 +97,6 @@
}
}
}
- return ref;
}
void ReferenceQueue::Dump(std::ostream& os) const {
@@ -140,6 +144,9 @@
}
cleared_references->EnqueueReference(ref);
}
+ // Delay disabling the read barrier until here so that the ClearReferent call above in
+ // transaction mode will trigger the read barrier.
+ DisableReadBarrierForReference(ref);
}
}
@@ -162,6 +169,9 @@
}
cleared_references->EnqueueReference(ref);
}
+ // Delay disabling the read barrier until here so that the ClearReferent call above in
+ // transaction mode will trigger the read barrier.
+ DisableReadBarrierForReference(ref->AsReference());
}
}
@@ -174,7 +184,9 @@
do {
mirror::HeapReference<mirror::Object>* referent_addr = ref->GetReferentReferenceAddr();
if (referent_addr->AsMirrorPtr() != nullptr) {
- visitor->MarkHeapReference(referent_addr);
+ // do_atomic_update is false because mutators can't access the referent due to the weak ref
+ // access blocking.
+ visitor->MarkHeapReference(referent_addr, /*do_atomic_update*/ false);
}
ref = ref->GetPendingNext();
} while (LIKELY(ref != head));