summaryrefslogtreecommitdiff
path: root/runtime/gc/reference_queue.cc
diff options
context:
space:
mode:
author Hiroshi Yamauchi <yamauchi@google.com> 2017-02-17 15:33:23 -0800
committer Hiroshi Yamauchi <yamauchi@google.com> 2017-02-21 13:50:11 -0800
commit057d977aed600843dd4a617dca7098555d79110b (patch)
tree1af506ef9e3ae36d44c355b0baa49b362d976f83 /runtime/gc/reference_queue.cc
parent6a669aac63ffc17b5e903aa4a1f285fe338eadcf (diff)
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
Diffstat (limited to 'runtime/gc/reference_queue.cc')
-rw-r--r--runtime/gc/reference_queue.cc16
1 files changed, 14 insertions, 2 deletions
diff --git a/runtime/gc/reference_queue.cc b/runtime/gc/reference_queue.cc
index 734caea371..fd5dcf9de6 100644
--- a/runtime/gc/reference_queue.cc
+++ b/runtime/gc/reference_queue.cc
@@ -67,6 +67,11 @@ ObjPtr<mirror::Reference> ReferenceQueue::DequeuePendingReference() {
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 @@ ObjPtr<mirror::Reference> ReferenceQueue::DequeuePendingReference() {
}
}
}
- return ref;
}
void ReferenceQueue::Dump(std::ostream& os) const {
@@ -140,6 +144,9 @@ void ReferenceQueue::ClearWhiteReferences(ReferenceQueue* cleared_references,
}
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 @@ void ReferenceQueue::EnqueueFinalizerReferences(ReferenceQueue* cleared_referenc
}
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 @@ void ReferenceQueue::ForwardSoftReferences(MarkObjectVisitor* visitor) {
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));