Visit class native roots from VisitReferences
Visit class roots when we call Class::VisitReferences instead of in
the class linker. This makes it easier to implement class unloading
since unmarked classes won't have their roots visited by the class
linker.
Bug: 22181835
Change-Id: I63f31e5ebef7b2a0b764b3ba3cb038b3f561b379
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index fc27315..069e346 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -680,6 +680,8 @@
// linked yet.
VisitStaticFieldsReferences<kVisitClass>(this, visitor);
}
+ // Since this class is reachable, we must also visit the associated roots when we scan it.
+ VisitNativeRoots(visitor, Runtime::Current()->GetClassLinker()->GetImagePointerSize());
}
template<ReadBarrierOption kReadBarrierOption>
@@ -816,20 +818,22 @@
if (sfields != nullptr) {
for (size_t i = 0, count = NumStaticFields(); i < count; ++i) {
auto* f = &sfields[i];
+ // Visit roots first in case the declaring class gets moved.
+ f->VisitRoots(visitor);
if (kIsDebugBuild && IsResolved()) {
CHECK_EQ(f->GetDeclaringClass(), this) << GetStatus();
}
- f->VisitRoots(visitor);
}
}
ArtField* const ifields = GetIFieldsUnchecked();
if (ifields != nullptr) {
for (size_t i = 0, count = NumInstanceFields(); i < count; ++i) {
auto* f = &ifields[i];
+ // Visit roots first in case the declaring class gets moved.
+ f->VisitRoots(visitor);
if (kIsDebugBuild && IsResolved()) {
CHECK_EQ(f->GetDeclaringClass(), this) << GetStatus();
}
- f->VisitRoots(visitor);
}
}
// We may see GetDirectMethodsPtr() == null with NumDirectMethods() != 0 if the root marking