summaryrefslogtreecommitdiff
path: root/runtime/gc/reference_processor.cc
diff options
context:
space:
mode:
author Hiroshi Yamauchi <yamauchi@google.com> 2016-12-19 11:44:47 -0800
committer Hiroshi Yamauchi <yamauchi@google.com> 2016-12-19 11:44:47 -0800
commit65f5f247a367af9d6b9ac63767b69ecf3ab079bc (patch)
treebff631b0efd7e8fe77be9c445ea9224e2b67433b /runtime/gc/reference_processor.cc
parent5b32b91d731d6187ada4c6fc804041b7b3b6903c (diff)
Fix race condition btw DelayReferenceRefernent vs Reference.clear().
Rename IsMarkedHeapReference to IsNullOrMarkedHeapReference. Move the null check from the caller of IsMarkedHeapReference into IsNullOrMarkedHeapReference. Make sure that the referent is only loaded once between the null check and the IsMarked call. Use a CAS in ConcurrentCopying::IsNullOrMarkedHeapReference when called from DelayReferenceRefernent. Bug: 33389022 Test: test-art-host without and with CC. Change-Id: I20edab4dac2a4bb02dbb72af0f09de77b55ac08e
Diffstat (limited to 'runtime/gc/reference_processor.cc')
-rw-r--r--runtime/gc/reference_processor.cc4
1 files changed, 3 insertions, 1 deletions
diff --git a/runtime/gc/reference_processor.cc b/runtime/gc/reference_processor.cc
index 081be968eb..c1548365c7 100644
--- a/runtime/gc/reference_processor.cc
+++ b/runtime/gc/reference_processor.cc
@@ -203,7 +203,9 @@ void ReferenceProcessor::DelayReferenceReferent(ObjPtr<mirror::Class> klass,
DCHECK(klass != nullptr);
DCHECK(klass->IsTypeOfReferenceClass());
mirror::HeapReference<mirror::Object>* referent = ref->GetReferentReferenceAddr();
- if (referent->AsMirrorPtr() != nullptr && !collector->IsMarkedHeapReference(referent)) {
+ // do_atomic_update needs to be true because this happens outside of the reference processing
+ // phase.
+ if (!collector->IsNullOrMarkedHeapReference(referent, /*do_atomic_update*/true)) {
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