Avoid unnecessary read barriers in mirror::Class.
Test: m test-art-host-gtest
Test: testrunner.py --host
Change-Id: Id98ebedf185bfc7f31eda506604c072f68b7a084
diff --git a/runtime/cha.cc b/runtime/cha.cc
index de4aebe..8e06fda 100644
--- a/runtime/cha.cc
+++ b/runtime/cha.cc
@@ -115,7 +115,7 @@
// if they have SingleImplementations methods defined by 'klass'.
// Skip all virtual methods that do not override methods from super class since they cannot be
// SingleImplementations for anything.
- int32_t vtbl_size = super->GetVTableLength<kDefaultVerifyFlags, kWithoutReadBarrier>();
+ int32_t vtbl_size = super->GetVTableLength<kDefaultVerifyFlags>();
ObjPtr<mirror::ClassLoader> loader =
klass->GetClassLoader<kDefaultVerifyFlags, kWithoutReadBarrier>();
for (int vtbl_index = 0; vtbl_index < vtbl_size; ++vtbl_index) {
@@ -131,7 +131,7 @@
// so start with a superclass and move up looking into a corresponding vtbl slot.
for (ObjPtr<mirror::Class> super_it = super;
super_it != nullptr &&
- super_it->GetVTableLength<kDefaultVerifyFlags, kWithoutReadBarrier>() > vtbl_index;
+ super_it->GetVTableLength<kDefaultVerifyFlags>() > vtbl_index;
super_it = super_it->GetSuperClass<kDefaultVerifyFlags, kWithoutReadBarrier>()) {
// Skip superclasses that are also going to be unloaded.
ObjPtr<mirror::ClassLoader> super_loader = super_it->
@@ -158,7 +158,7 @@
// Check all possible interface methods too.
ObjPtr<mirror::IfTable> iftable = klass->GetIfTable<kDefaultVerifyFlags, kWithoutReadBarrier>();
- const size_t ifcount = klass->GetIfTableCount<kDefaultVerifyFlags, kWithoutReadBarrier>();
+ const size_t ifcount = klass->GetIfTableCount<kDefaultVerifyFlags>();
for (size_t i = 0; i < ifcount; ++i) {
ObjPtr<mirror::Class> interface =
iftable->GetInterface<kDefaultVerifyFlags, kWithoutReadBarrier>(i);
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 10f395b..0766999 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -1884,7 +1884,7 @@
}
auto* iftable = klass->GetIfTable<kVerifyNone, kWithoutReadBarrier>();
if (iftable != nullptr) {
- int32_t ifcount = klass->GetIfTableCount<kVerifyNone, kWithoutReadBarrier>();
+ int32_t ifcount = klass->GetIfTableCount<kVerifyNone>();
for (int32_t i = 0; i != ifcount; ++i) {
mirror::PointerArray* unpatched_ifarray =
iftable->GetMethodArrayOrNull<kVerifyNone, kWithoutReadBarrier>(i);
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index 3c41836..6b9ba8c 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -294,16 +294,20 @@
}
inline bool Class::HasVTable() {
- return GetVTable() != nullptr || ShouldHaveEmbeddedVTable();
+ // No read barrier is needed for comparing with null.
+ return GetVTable<kDefaultVerifyFlags, kWithoutReadBarrier>() != nullptr ||
+ ShouldHaveEmbeddedVTable();
}
-template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
+template<VerifyObjectFlags kVerifyFlags>
inline int32_t Class::GetVTableLength() {
if (ShouldHaveEmbeddedVTable<kVerifyFlags>()) {
return GetEmbeddedVTableLength();
}
- return GetVTable<kVerifyFlags, kReadBarrierOption>() != nullptr ?
- GetVTable<kVerifyFlags, kReadBarrierOption>()->GetLength() : 0;
+ // We do not need a read barrier here as the length is constant,
+ // both from-space and to-space vtables shall yield the same result.
+ ObjPtr<PointerArray> vtable = GetVTable<kVerifyFlags, kWithoutReadBarrier>();
+ return vtable != nullptr ? vtable->GetLength() : 0;
}
template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
@@ -311,9 +315,9 @@
if (ShouldHaveEmbeddedVTable<kVerifyFlags>()) {
return GetEmbeddedVTableEntry(i, pointer_size);
}
- auto* vtable = GetVTable<kVerifyFlags, kReadBarrierOption>();
+ ObjPtr<PointerArray> vtable = GetVTable<kVerifyFlags, kReadBarrierOption>();
DCHECK(vtable != nullptr);
- return vtable->template GetElementPtrSize<ArtMethod*, kVerifyFlags>(i, pointer_size);
+ return vtable->GetElementPtrSize<ArtMethod*, kVerifyFlags>(i, pointer_size);
}
template<VerifyObjectFlags kVerifyFlags>
@@ -623,9 +627,11 @@
return ret.Ptr();
}
-template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
+template<VerifyObjectFlags kVerifyFlags>
inline int32_t Class::GetIfTableCount() {
- return GetIfTable<kVerifyFlags, kReadBarrierOption>()->Count();
+ // We do not need a read barrier here as the length is constant,
+ // both from-space and to-space iftables shall yield the same result.
+ return GetIfTable<kVerifyFlags, kWithoutReadBarrier>()->Count();
}
inline void Class::SetIfTable(ObjPtr<IfTable> new_iftable) {
@@ -969,7 +975,17 @@
// We do not need a read barrier here as the primitive type is constant,
// both from-space and to-space component type classes shall yield the same result.
ObjPtr<Class> const component_type = GetComponentType<kVerifyFlags, kWithoutReadBarrier>();
- return component_type != nullptr && !component_type->IsPrimitive<kVerifyFlags>();
+ constexpr VerifyObjectFlags kNewFlags = RemoveThisFlags(kVerifyFlags);
+ return component_type != nullptr && !component_type->IsPrimitive<kNewFlags>();
+}
+
+template<VerifyObjectFlags kVerifyFlags>
+bool Class::IsPrimitiveArray() {
+ // We do not need a read barrier here as the primitive type is constant,
+ // both from-space and to-space component type classes shall yield the same result.
+ ObjPtr<Class> const component_type = GetComponentType<kVerifyFlags, kWithoutReadBarrier>();
+ constexpr VerifyObjectFlags kNewFlags = RemoveThisFlags(kVerifyFlags);
+ return component_type != nullptr && component_type->IsPrimitive<kNewFlags>();
}
inline bool Class::IsAssignableFrom(ObjPtr<Class> src) {
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 9923cd3..bb54b3d 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -422,13 +422,6 @@
return GetPrimitiveType<kVerifyFlags>() == Primitive::kPrimVoid;
}
- template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
- bool IsPrimitiveArray() REQUIRES_SHARED(Locks::mutator_lock_) {
- return IsArrayClass<kVerifyFlags>() &&
- GetComponentType<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>()->
- IsPrimitive();
- }
-
// Depth of class from java.lang.Object
uint32_t Depth() REQUIRES_SHARED(Locks::mutator_lock_);
@@ -466,7 +459,8 @@
}
bool IsObjectClass() REQUIRES_SHARED(Locks::mutator_lock_) {
- return !IsPrimitive() && GetSuperClass() == nullptr;
+ // No read barrier is needed for comparing with null.
+ return !IsPrimitive() && GetSuperClass<kDefaultVerifyFlags, kWithoutReadBarrier>() == nullptr;
}
bool IsInstantiableNonArray() REQUIRES_SHARED(Locks::mutator_lock_) {
@@ -484,6 +478,9 @@
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
ALWAYS_INLINE bool IsObjectArrayClass() REQUIRES_SHARED(Locks::mutator_lock_);
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ bool IsPrimitiveArray() REQUIRES_SHARED(Locks::mutator_lock_);
+
// Creates a raw object instance but does not invoke the default constructor.
template<bool kIsInstrumented, bool kCheckAddFinalizer = true>
ALWAYS_INLINE ObjPtr<Object> Alloc(Thread* self, gc::AllocatorType allocator_type)
@@ -619,7 +616,8 @@
void SetSuperClass(ObjPtr<Class> new_super_class) REQUIRES_SHARED(Locks::mutator_lock_);
bool HasSuperClass() REQUIRES_SHARED(Locks::mutator_lock_) {
- return GetSuperClass() != nullptr;
+ // No read barrier is needed for comparing with null.
+ return GetSuperClass<kDefaultVerifyFlags, kWithoutReadBarrier>() != nullptr;
}
static constexpr MemberOffset SuperClassOffset() {
@@ -798,8 +796,7 @@
static MemberOffset EmbeddedVTableEntryOffset(uint32_t i, PointerSize pointer_size);
- template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
- ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
int32_t GetVTableLength() REQUIRES_SHARED(Locks::mutator_lock_);
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
@@ -934,8 +931,7 @@
return (GetAccessFlags() & kAccRecursivelyInitialized) != 0;
}
- template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
- ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
ALWAYS_INLINE int32_t GetIfTableCount() REQUIRES_SHARED(Locks::mutator_lock_);
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
@@ -1202,7 +1198,8 @@
// Returns true if the class loader is null, ie the class loader is the boot strap class loader.
bool IsBootStrapClassLoaded() REQUIRES_SHARED(Locks::mutator_lock_) {
- return GetClassLoader() == nullptr;
+ // No read barrier is needed for comparing with null.
+ return GetClassLoader<kDefaultVerifyFlags, kWithoutReadBarrier>() == nullptr;
}
static size_t ImTableEntrySize(PointerSize pointer_size) {
diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h
index fcb7479..2c2ad9b 100644
--- a/runtime/mirror/object-inl.h
+++ b/runtime/mirror/object-inl.h
@@ -156,7 +156,7 @@
inline bool Object::IsObjectArray() {
// We do not need a read barrier here as the primitive type is constant,
// both from-space and to-space component type classes shall yield the same result.
- constexpr auto kNewFlags = RemoveThisFlags(kVerifyFlags);
+ constexpr VerifyObjectFlags kNewFlags = RemoveThisFlags(kVerifyFlags);
return IsArrayInstance<kVerifyFlags>() &&
!GetClass<kNewFlags, kWithoutReadBarrier>()->
template GetComponentType<kNewFlags, kWithoutReadBarrier>()->IsPrimitive();
@@ -197,7 +197,7 @@
// We do not need a read barrier here as the primitive type is constant,
// both from-space and to-space component type classes shall yield the same result.
ObjPtr<Class> klass = GetClass<kVerifyFlags, kWithoutReadBarrier>();
- constexpr auto kNewFlags = RemoveThisFlags(kVerifyFlags);
+ constexpr VerifyObjectFlags kNewFlags = RemoveThisFlags(kVerifyFlags);
ObjPtr<Class> const component_type = klass->GetComponentType<kNewFlags, kWithoutReadBarrier>();
return component_type != nullptr &&
component_type->GetPrimitiveType<kNewFlags>() == kType;
@@ -340,7 +340,7 @@
// values is OK because of that.
static constexpr ReadBarrierOption kRBO = kWithoutReadBarrier;
size_t result;
- constexpr auto kNewFlags = RemoveThisFlags(kVerifyFlags);
+ constexpr VerifyObjectFlags kNewFlags = RemoveThisFlags(kVerifyFlags);
if (IsArrayInstance<kVerifyFlags>()) {
result = AsArray<kNewFlags>()->template SizeOf<kNewFlags, kRBO>();
} else if (IsClass<kNewFlags>()) {