summaryrefslogtreecommitdiff
path: root/runtime/gc/reference_queue.cc
diff options
context:
space:
mode:
author Fred Shih <ffred@google.com> 2014-06-09 15:19:54 -0700
committer Fred Shih <ffred@google.com> 2014-06-10 10:33:02 -0700
commit530e1b54887b6b5e7d648170096e22a5f1850ea8 (patch)
treec273698b2e51c29f373c18ece5eac5635bbbe037 /runtime/gc/reference_queue.cc
parent5d4a3fedcb18dadba5f50661e2a6d86890adfcbc (diff)
Reduced frequency of blocks for concurrent gc
Immediately return for references that are marked before reference processing without blocking. Soft references are kept in the queue until the reference processor stops preserving, after which, all marked references are removed. Finalizer references will still block on get(). Bug: 15471830 Change-Id: I588fcaef40b79ed7c95a4aa7f4fc2e17ee0c288f
Diffstat (limited to 'runtime/gc/reference_queue.cc')
-rw-r--r--runtime/gc/reference_queue.cc21
1 files changed, 11 insertions, 10 deletions
diff --git a/runtime/gc/reference_queue.cc b/runtime/gc/reference_queue.cc
index caacef5cf0..3910c297a2 100644
--- a/runtime/gc/reference_queue.cc
+++ b/runtime/gc/reference_queue.cc
@@ -160,22 +160,23 @@ void ReferenceQueue::EnqueueFinalizerReferences(ReferenceQueue& cleared_referenc
}
}
-void ReferenceQueue::PreserveSomeSoftReferences(IsMarkedCallback* preserve_callback, void* arg) {
- ReferenceQueue cleared;
- while (!IsEmpty()) {
- mirror::Reference* ref = DequeuePendingReference();
+void ReferenceQueue::ForwardSoftReferences(IsMarkedCallback* preserve_callback,
+ void* arg) {
+ if (UNLIKELY(IsEmpty())) {
+ return;
+ }
+ mirror::Reference* const head = list_;
+ mirror::Reference* ref = head;
+ do {
mirror::Object* referent = ref->GetReferent<kWithoutReadBarrier>();
if (referent != nullptr) {
mirror::Object* forward_address = preserve_callback(referent, arg);
- if (forward_address == nullptr) {
- // Either the reference isn't marked or we don't wish to preserve it.
- cleared.EnqueuePendingReference(ref);
- } else if (forward_address != referent) {
+ if (forward_address != nullptr && forward_address != referent) {
ref->SetReferent<false>(forward_address);
}
}
- }
- list_ = cleared.GetList();
+ ref = ref->GetPendingNext();
+ } while (LIKELY(ref != head));
}
} // namespace gc