Add and use a read-barrier free NeedInitializationCheck method.

The JIT may be working with ArtMethod that are in the process of
being deleted.

Bug: 142001849
Test: 674-hiddenapi
Change-Id: I3632ba6f49bcf54a29bd92882eb343b92945ef28
diff --git a/runtime/art_method-inl.h b/runtime/art_method-inl.h
index 3aec1c3..3f87154 100644
--- a/runtime/art_method-inl.h
+++ b/runtime/art_method-inl.h
@@ -430,6 +430,16 @@
   imt_index_ = ~ImTable::GetImtIndex(this);
 }
 
+template <ReadBarrierOption kReadBarrierOption>
+bool ArtMethod::NeedsInitializationCheck() {
+  // Knowing if the class is visibly initialized is only for JIT/AOT compiled
+  // code to avoid the memory barrier. For callers of `NeedsInitializationCheck`
+  // it's enough to just check whether the class is initialized.
+  return IsStatic() &&
+      !IsConstructor() &&
+      !GetDeclaringClass<kReadBarrierOption>()->IsInitialized();
+}
+
 }  // namespace art
 
 #endif  // ART_RUNTIME_ART_METHOD_INL_H_
diff --git a/runtime/art_method.cc b/runtime/art_method.cc
index d533cce..646f73d 100644
--- a/runtime/art_method.cc
+++ b/runtime/art_method.cc
@@ -881,11 +881,4 @@
         method->GetDeclaringClass<kReadBarrierOption>()->IsErroneous());
 }
 
-bool ArtMethod::NeedsInitializationCheck() {
-  // Knowing if the class is visibly initialized is only for JIT/AOT compiled
-  // code to avoid the memory barrier. For callers of `NeedsInitializationCheck`
-  // it's enough to just check whether the class is initialized.
-  return IsStatic() && !IsConstructor() && !GetDeclaringClass()->IsInitialized();
-}
-
 }  // namespace art
diff --git a/runtime/art_method.h b/runtime/art_method.h
index 46cc1ed..612c566 100644
--- a/runtime/art_method.h
+++ b/runtime/art_method.h
@@ -367,6 +367,7 @@
 
   // Returns whether the method can be invoked directly or needs a
   // class initialization check.
+  template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
   bool NeedsInitializationCheck() REQUIRES_SHARED(Locks::mutator_lock_);
 
   // Returns true if this method could be overridden by a default method.
diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc
index 70c6822..5249f22 100644
--- a/runtime/jit/jit_code_cache.cc
+++ b/runtime/jit/jit_code_cache.cc
@@ -757,8 +757,11 @@
       data->SetCode(code_ptr);
       instrumentation::Instrumentation* instrum = Runtime::Current()->GetInstrumentation();
       for (ArtMethod* m : data->GetMethods()) {
-        if (!m->NeedsInitializationCheck()) {
-          instrum->UpdateMethodsCode(m, method_header->GetEntryPoint());
+        // Because `m` might be in the process of being deleted:
+        // - Call the dedicated method instead of the more generic UpdateMethodsCode
+        // - Check the class status without a read barrier.
+        if (!m->NeedsInitializationCheck<kWithoutReadBarrier>()) {
+          instrum->UpdateNativeMethodsCodeToJitCode(m, method_header->GetEntryPoint());
         }
       }
     } else {
@@ -1608,9 +1611,10 @@
       // can avoid a few expensive GenericJNI calls.
       instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
       for (ArtMethod* m : data->GetMethods()) {
-        // Call the dedicated method instead of the more generic UpdateMethodsCode, because
-        // `m` might be in the process of being deleted.
-        if (!m->NeedsInitializationCheck()) {
+        // Because `m` might be in the process of being deleted:
+        // - Call the dedicated method instead of the more generic UpdateMethodsCode
+        // - Check the class status without a read barrier.
+        if (!m->NeedsInitializationCheck<kWithoutReadBarrier>()) {
           instrumentation->UpdateNativeMethodsCodeToJitCode(m, entrypoint);
         }
       }