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() {