diff options
| -rw-r--r-- | runtime/gc/collector/concurrent_copying.cc | 17 | ||||
| -rw-r--r-- | runtime/gc/collector/concurrent_copying.h | 7 |
2 files changed, 23 insertions, 1 deletions
diff --git a/runtime/gc/collector/concurrent_copying.cc b/runtime/gc/collector/concurrent_copying.cc index 7736568620..53aa9ba67b 100644 --- a/runtime/gc/collector/concurrent_copying.cc +++ b/runtime/gc/collector/concurrent_copying.cc @@ -860,6 +860,21 @@ class ConcurrentCopying::ImmuneSpaceScanObjVisitor { ConcurrentCopying* const collector_; }; +template <bool kNoUnEvac> +void ConcurrentCopying::ScanDirtyObject(mirror::Object* obj) { + Scan<kNoUnEvac>(obj); + // Set the read-barrier state of a reference-type object to gray if its + // referent is not marked yet. This is to ensure that if GetReferent() is + // called, it triggers the read-barrier to process the referent before use. + if (UNLIKELY((obj->GetClass<kVerifyNone, kWithoutReadBarrier>()->IsTypeOfReferenceClass()))) { + mirror::Object* referent = + obj->AsReference<kVerifyNone, kWithoutReadBarrier>()->GetReferent<kWithoutReadBarrier>(); + if (referent != nullptr && !IsInToSpace(referent)) { + obj->AtomicSetReadBarrierState(ReadBarrier::NonGrayState(), ReadBarrier::GrayState()); + } + } +} + // Concurrently mark roots that are guarded by read barriers and process the mark stack. void ConcurrentCopying::MarkingPhase() { TimingLogger::ScopedTiming split("MarkingPhase", GetTimings()); @@ -924,7 +939,7 @@ void ConcurrentCopying::MarkingPhase() { LOG(FATAL) << "Scanning " << obj << " not in unevac space"; } } - Scan<true>(obj); + ScanDirtyObject</*kNoUnEvac*/ true>(obj); }, accounting::CardTable::kCardDirty - 1); } diff --git a/runtime/gc/collector/concurrent_copying.h b/runtime/gc/collector/concurrent_copying.h index 237e070d1a..e251fbccfe 100644 --- a/runtime/gc/collector/concurrent_copying.h +++ b/runtime/gc/collector/concurrent_copying.h @@ -161,6 +161,13 @@ class ConcurrentCopying : public GarbageCollector { template <bool kNoUnEvac> void Scan(mirror::Object* to_ref) REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!mark_stack_lock_); + // Scan the reference fields of object 'obj' in the dirty cards during + // card-table scan. In addition to visiting the references, it also sets the + // read-barrier state to gray for Reference-type objects to ensure that + // GetReferent() called on these objects calls the read-barrier on the referent. + template <bool kNoUnEvac> + void ScanDirtyObject(mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_) + REQUIRES(!mark_stack_lock_); // Process a field. template <bool kNoUnEvac> void Process(mirror::Object* obj, MemberOffset offset) |