summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/gc/collector/concurrent_copying.cc17
-rw-r--r--runtime/gc/collector/concurrent_copying.h7
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)