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);
}
}