Reduce class loader updating overhead.
Avoid unnecessary read barrier for comparing class loader agianst
null. Avoid transaction check.
Deleted the helper class to simplify the code.
The time goes from ~3.8ms to ~2.9ms on Maps.
Test: test-art-host
Bug: 116052292
Change-Id: I4a966a9bb39400ba58d7cf3e0b2c8ab4747d65ed
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index cc4f56c..63e7915 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1543,26 +1543,6 @@
}
}
-// Update the class loader. Should only be used on classes in the image space.
-class UpdateClassLoaderVisitor {
- public:
- UpdateClassLoaderVisitor(gc::space::ImageSpace* space, ObjPtr<mirror::ClassLoader> class_loader)
- : space_(space),
- class_loader_(class_loader) {}
-
- bool operator()(ObjPtr<mirror::Class> klass) const REQUIRES_SHARED(Locks::mutator_lock_) {
- // Do not update class loader for boot image classes where the app image
- // class loader is only the initiating loader but not the defining loader.
- if (klass->GetClassLoader() != nullptr) {
- klass->SetClassLoader(class_loader_);
- }
- return true;
- }
-
- gc::space::ImageSpace* const space_;
- ObjPtr<mirror::ClassLoader> const class_loader_;
-};
-
static std::unique_ptr<const DexFile> OpenOatDexFile(const OatFile* oat_file,
const char* location,
std::string* error_msg)
@@ -2036,9 +2016,17 @@
ScopedTrace trace("AppImage:UpdateClassLoaders");
// Update class loader and resolved strings. If added_class_table is false, the resolved
// strings were forwarded UpdateAppImageClassLoadersAndDexCaches.
- UpdateClassLoaderVisitor visitor(space, class_loader.Get());
+ ObjPtr<mirror::ClassLoader> loader(class_loader.Get());
for (const ClassTable::TableSlot& root : temp_set) {
- visitor(root.Read());
+ // Note: We probably don't need the read barrier unless we copy the app image objects into
+ // the region space.
+ ObjPtr<mirror::Class> klass(root.Read());
+ // Do not update class loader for boot image classes where the app image
+ // class loader is only the initiating loader but not the defining loader.
+ // Avoid read barrier since we are comparing against null.
+ if (klass->GetClassLoader<kDefaultVerifyFlags, kWithoutReadBarrier>() != nullptr) {
+ klass->SetClassLoader</*kCheckTransaction=*/ false>(loader);
+ }
}
}
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index 6b9ba8c..185ae3b 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -1102,6 +1102,16 @@
return component->IsPrimitive() || component->CannotBeAssignedFromOtherTypes();
}
+template <bool kCheckTransaction>
+inline void Class::SetClassLoader(ObjPtr<ClassLoader> new_class_loader) {
+ if (kCheckTransaction && Runtime::Current()->IsActiveTransaction()) {
+ SetFieldObject<true>(OFFSET_OF_OBJECT_MEMBER(Class, class_loader_), new_class_loader);
+ } else {
+ DCHECK(!Runtime::Current()->IsActiveTransaction());
+ SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(Class, class_loader_), new_class_loader);
+ }
+}
+
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index e33e407..83d76a9 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -427,14 +427,6 @@
return GetClassRoot<mirror::Throwable>()->IsAssignableFrom(this);
}
-void Class::SetClassLoader(ObjPtr<ClassLoader> new_class_loader) {
- if (Runtime::Current()->IsActiveTransaction()) {
- SetFieldObject<true>(OFFSET_OF_OBJECT_MEMBER(Class, class_loader_), new_class_loader);
- } else {
- SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(Class, class_loader_), new_class_loader);
- }
-}
-
template <typename SignatureType>
static inline ArtMethod* FindInterfaceMethodWithSignature(ObjPtr<Class> klass,
const StringPiece& name,
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index bb54b3d..c38cc86 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -628,6 +628,7 @@
ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
ClassLoader* GetClassLoader() ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_);
+ template <bool kCheckTransaction = true>
void SetClassLoader(ObjPtr<ClassLoader> new_cl) REQUIRES_SHARED(Locks::mutator_lock_);
static constexpr MemberOffset DexCacheOffset() {