Propagate the read barrier option to Class::VisitNativeRoots.
Propagate the read barrier option from Object::VisitReferences to
Class::VisitNativeRoots.
This is a step toward the GC thread avoiding graying objects (and
reducing dirty pages) in the immune spaces.
Bug: 12687968
Change-Id: I29c4126a4ad4c40e63a934e62451fb3fb36aad43
diff --git a/runtime/art_field-inl.h b/runtime/art_field-inl.h
index d911497..564a857 100644
--- a/runtime/art_field-inl.h
+++ b/runtime/art_field-inl.h
@@ -33,9 +33,10 @@
namespace art {
+template<ReadBarrierOption kReadBarrierOption>
inline mirror::Class* ArtField::GetDeclaringClass() {
GcRootSource gc_root_source(this);
- mirror::Class* result = declaring_class_.Read(&gc_root_source);
+ mirror::Class* result = declaring_class_.Read<kReadBarrierOption>(&gc_root_source);
DCHECK(result != nullptr);
DCHECK(result->IsLoaded() || result->IsErroneous()) << result->GetStatus();
return result;
diff --git a/runtime/art_field.h b/runtime/art_field.h
index b64b70f..aaccbf3 100644
--- a/runtime/art_field.h
+++ b/runtime/art_field.h
@@ -41,6 +41,7 @@
public:
ArtField();
+ template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
mirror::Class* GetDeclaringClass() SHARED_REQUIRES(Locks::mutator_lock_);
void SetDeclaringClass(mirror::Class *new_declaring_class)
diff --git a/runtime/art_method-inl.h b/runtime/art_method-inl.h
index 7647ad6..26450c4 100644
--- a/runtime/art_method-inl.h
+++ b/runtime/art_method-inl.h
@@ -395,8 +395,9 @@
return GetDeclaringClass()->GetDexCache();
}
+template<ReadBarrierOption kReadBarrierOption>
inline bool ArtMethod::IsProxyMethod() {
- return GetDeclaringClass()->IsProxyClass();
+ return GetDeclaringClass<kReadBarrierOption>()->IsProxyClass();
}
inline ArtMethod* ArtMethod::GetInterfaceMethodIfProxy(size_t pointer_size) {
@@ -438,24 +439,24 @@
return type;
}
-template<typename RootVisitorType>
+template<ReadBarrierOption kReadBarrierOption, typename RootVisitorType>
void ArtMethod::VisitRoots(RootVisitorType& visitor, size_t pointer_size) {
- ArtMethod* interface_method = nullptr;
- mirror::Class* klass = declaring_class_.Read();
- if (LIKELY(klass != nullptr)) {
+ if (LIKELY(!declaring_class_.IsNull())) {
+ visitor.VisitRoot(declaring_class_.AddressWithoutBarrier());
+ mirror::Class* klass = declaring_class_.Read<kReadBarrierOption>();
if (UNLIKELY(klass->IsProxyClass())) {
// For normal methods, dex cache shortcuts will be visited through the declaring class.
// However, for proxies we need to keep the interface method alive, so we visit its roots.
- interface_method = mirror::DexCache::GetElementPtrSize(
+ ArtMethod* interface_method = mirror::DexCache::GetElementPtrSize(
GetDexCacheResolvedMethods(pointer_size),
GetDexMethodIndex(),
pointer_size);
DCHECK(interface_method != nullptr);
DCHECK_EQ(interface_method,
- Runtime::Current()->GetClassLinker()->FindMethodForProxy(klass, this));
+ Runtime::Current()->GetClassLinker()->FindMethodForProxy<kReadBarrierOption>(
+ klass, this));
interface_method->VisitRoots(visitor, pointer_size);
}
- visitor.VisitRoot(declaring_class_.AddressWithoutBarrier());
// We know we don't have profiling information if the class hasn't been verified. Note
// that this check also ensures the IsNative call can be made, as IsNative expects a fully
// created class (and not a retired one).
@@ -463,7 +464,7 @@
// Runtime methods and native methods use the same field as the profiling info for
// storing their own data (jni entrypoint for native methods, and ImtConflictTable for
// some runtime methods).
- if (!IsNative() && !IsRuntimeMethod()) {
+ if (!IsNative<kReadBarrierOption>() && !IsRuntimeMethod()) {
ProfilingInfo* profiling_info = GetProfilingInfo(pointer_size);
if (profiling_info != nullptr) {
profiling_info->VisitRoots(visitor);
diff --git a/runtime/art_method.h b/runtime/art_method.h
index a012a5a..2b025f8 100644
--- a/runtime/art_method.h
+++ b/runtime/art_method.h
@@ -340,6 +340,7 @@
return (GetAccessFlags() & kAccSynthetic) != 0;
}
+ template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
bool IsProxyMethod() SHARED_REQUIRES(Locks::mutator_lock_);
bool SkipAccessChecks() {
@@ -564,7 +565,7 @@
SHARED_REQUIRES(Locks::mutator_lock_);
// NO_THREAD_SAFETY_ANALYSIS since we don't know what the callback requires.
- template<typename RootVisitorType>
+ template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier, typename RootVisitorType>
void VisitRoots(RootVisitorType& visitor, size_t pointer_size) NO_THREAD_SAFETY_ANALYSIS;
const DexFile* GetDexFile() SHARED_REQUIRES(Locks::mutator_lock_);
diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h
index f3e260b..f2575f7 100644
--- a/runtime/class_linker-inl.h
+++ b/runtime/class_linker-inl.h
@@ -225,6 +225,34 @@
return klass;
}
+template<ReadBarrierOption kReadBarrierOption>
+ArtMethod* ClassLinker::FindMethodForProxy(mirror::Class* proxy_class, ArtMethod* proxy_method) {
+ DCHECK(proxy_class->IsProxyClass());
+ DCHECK(proxy_method->IsProxyMethod<kReadBarrierOption>());
+ {
+ Thread* const self = Thread::Current();
+ ReaderMutexLock mu(self, dex_lock_);
+ // Locate the dex cache of the original interface/Object
+ for (const DexCacheData& data : dex_caches_) {
+ if (!self->IsJWeakCleared(data.weak_root) &&
+ proxy_method->HasSameDexCacheResolvedTypes(data.resolved_types,
+ image_pointer_size_)) {
+ mirror::DexCache* dex_cache = down_cast<mirror::DexCache*>(
+ self->DecodeJObject(data.weak_root));
+ if (dex_cache != nullptr) {
+ ArtMethod* resolved_method = dex_cache->GetResolvedMethod(
+ proxy_method->GetDexMethodIndex(), image_pointer_size_);
+ CHECK(resolved_method != nullptr);
+ return resolved_method;
+ }
+ }
+ }
+ }
+ LOG(FATAL) << "Didn't find dex cache for " << PrettyClass(proxy_class) << " "
+ << PrettyMethod(proxy_method);
+ UNREACHABLE();
+}
+
} // namespace art
#endif // ART_RUNTIME_CLASS_LINKER_INL_H_
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index d03b57c..343bc8f 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -4248,33 +4248,6 @@
return DotToDescriptor(name->ToModifiedUtf8().c_str());
}
-ArtMethod* ClassLinker::FindMethodForProxy(mirror::Class* proxy_class, ArtMethod* proxy_method) {
- DCHECK(proxy_class->IsProxyClass());
- DCHECK(proxy_method->IsProxyMethod());
- {
- Thread* const self = Thread::Current();
- ReaderMutexLock mu(self, dex_lock_);
- // Locate the dex cache of the original interface/Object
- for (const DexCacheData& data : dex_caches_) {
- if (!self->IsJWeakCleared(data.weak_root) &&
- proxy_method->HasSameDexCacheResolvedTypes(data.resolved_types,
- image_pointer_size_)) {
- mirror::DexCache* dex_cache = down_cast<mirror::DexCache*>(
- self->DecodeJObject(data.weak_root));
- if (dex_cache != nullptr) {
- ArtMethod* resolved_method = dex_cache->GetResolvedMethod(
- proxy_method->GetDexMethodIndex(), image_pointer_size_);
- CHECK(resolved_method != nullptr);
- return resolved_method;
- }
- }
- }
- }
- LOG(FATAL) << "Didn't find dex cache for " << PrettyClass(proxy_class) << " "
- << PrettyMethod(proxy_method);
- UNREACHABLE();
-}
-
void ClassLinker::CreateProxyConstructor(Handle<mirror::Class> klass, ArtMethod* out) {
// Create constructor for Proxy that must initialize the method.
CHECK_EQ(GetClassRoot(kJavaLangReflectProxy)->NumDirectMethods(), 18u);
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index f6ce545..3cf0fb6 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -482,6 +482,7 @@
SHARED_REQUIRES(Locks::mutator_lock_);
std::string GetDescriptorForProxy(mirror::Class* proxy_class)
SHARED_REQUIRES(Locks::mutator_lock_);
+ template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
ArtMethod* FindMethodForProxy(mirror::Class* proxy_class, ArtMethod* proxy_method)
REQUIRES(!dex_lock_)
SHARED_REQUIRES(Locks::mutator_lock_);
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index dfb728f..f8436c3 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -534,7 +534,7 @@
inline MemberOffset Class::GetFirstReferenceInstanceFieldOffset() {
Class* super_class = GetSuperClass<kVerifyFlags, kReadBarrierOption>();
return (super_class != nullptr)
- ? MemberOffset(RoundUp(super_class->GetObjectSize(),
+ ? MemberOffset(RoundUp(super_class->GetObjectSize<kVerifyFlags, kReadBarrierOption>(),
sizeof(mirror::HeapReference<mirror::Object>)))
: ClassOffset();
}
@@ -780,7 +780,8 @@
}
if (kVisitNativeRoots) {
// Since this class is reachable, we must also visit the associated roots when we scan it.
- VisitNativeRoots(visitor, Runtime::Current()->GetClassLinker()->GetImagePointerSize());
+ VisitNativeRoots<kReadBarrierOption>(
+ visitor, Runtime::Current()->GetClassLinker()->GetImagePointerSize());
}
}
@@ -919,24 +920,24 @@
return GetFieldPtr<GcRoot<String>*>(DexCacheStringsOffset());
}
-template<class Visitor>
+template<ReadBarrierOption kReadBarrierOption, class Visitor>
void mirror::Class::VisitNativeRoots(Visitor& visitor, size_t pointer_size) {
for (ArtField& field : GetSFieldsUnchecked()) {
// Visit roots first in case the declaring class gets moved.
field.VisitRoots(visitor);
if (kIsDebugBuild && IsResolved()) {
- CHECK_EQ(field.GetDeclaringClass(), this) << GetStatus();
+ CHECK_EQ(field.GetDeclaringClass<kReadBarrierOption>(), this) << GetStatus();
}
}
for (ArtField& field : GetIFieldsUnchecked()) {
// Visit roots first in case the declaring class gets moved.
field.VisitRoots(visitor);
if (kIsDebugBuild && IsResolved()) {
- CHECK_EQ(field.GetDeclaringClass(), this) << GetStatus();
+ CHECK_EQ(field.GetDeclaringClass<kReadBarrierOption>(), this) << GetStatus();
}
}
for (ArtMethod& method : GetMethods(pointer_size)) {
- method.VisitRoots(visitor, pointer_size);
+ method.VisitRoots<kReadBarrierOption>(visitor, pointer_size);
}
}
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 8c20fa6..5235a3e 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -1156,7 +1156,7 @@
// Visit native roots visits roots which are keyed off the native pointers such as ArtFields and
// ArtMethods.
- template<class Visitor>
+ template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier, class Visitor>
void VisitNativeRoots(Visitor& visitor, size_t pointer_size)
SHARED_REQUIRES(Locks::mutator_lock_);