Fix soft reference clearing issue.
There was a bug where we would check that the pending next field was
non null before enqueueing up cleared references. This was causing
references to not get queued up during ProcessReferences.
Bug: 10626133
Change-Id: Ic1e00e42045092280b4abb3d41f1c58f7adbc3de
diff --git a/runtime/gc/collector/mark_sweep.cc b/runtime/gc/collector/mark_sweep.cc
index 953fbf9..92bfc4e 100644
--- a/runtime/gc/collector/mark_sweep.cc
+++ b/runtime/gc/collector/mark_sweep.cc
@@ -1342,18 +1342,28 @@
}
Thread* self = Thread::Current();
// TODO: Remove these locks, and use atomic stacks for storing references?
+ // We need to check that the references haven't already been enqueued since we can end up
+ // scanning the same reference multiple times due to dirty cards.
if (klass->IsSoftReferenceClass()) {
MutexLock mu(self, *heap_->GetSoftRefQueueLock());
- heap_->EnqueuePendingReference(obj, &soft_reference_list_);
+ if (!heap_->IsEnqueued(obj)) {
+ heap_->EnqueuePendingReference(obj, &soft_reference_list_);
+ }
} else if (klass->IsWeakReferenceClass()) {
MutexLock mu(self, *heap_->GetWeakRefQueueLock());
- heap_->EnqueuePendingReference(obj, &weak_reference_list_);
+ if (!heap_->IsEnqueued(obj)) {
+ heap_->EnqueuePendingReference(obj, &weak_reference_list_);
+ }
} else if (klass->IsFinalizerReferenceClass()) {
MutexLock mu(self, *heap_->GetFinalizerRefQueueLock());
- heap_->EnqueuePendingReference(obj, &finalizer_reference_list_);
+ if (!heap_->IsEnqueued(obj)) {
+ heap_->EnqueuePendingReference(obj, &finalizer_reference_list_);
+ }
} else if (klass->IsPhantomReferenceClass()) {
MutexLock mu(self, *heap_->GetPhantomRefQueueLock());
- heap_->EnqueuePendingReference(obj, &phantom_reference_list_);
+ if (!heap_->IsEnqueued(obj)) {
+ heap_->EnqueuePendingReference(obj, &phantom_reference_list_);
+ }
} else {
LOG(FATAL) << "Invalid reference type " << PrettyClass(klass)
<< " " << std::hex << klass->GetAccessFlags();
@@ -1499,7 +1509,6 @@
return heap_->GetMarkBitmap()->Test(object);
}
-
// Unlink the reference list clearing references objects with white
// referents. Cleared references registered to a reference queue are
// scheduled for appending by the heap worker thread.