Remove CHA dependencies for class unloading when JIT is disabled
When a linear alloc is unloaded, remove the corresponding CHA
dependencies to prevent any dangling pointers to ArtMethods.
Bug: 63905544
Bug: 63467744
Test: test-art-host
Change-Id: I6f54c6e774daef1a64c6a02a17eb5f5ab98841fd
diff --git a/runtime/cha.cc b/runtime/cha.cc
index 8eeebf3..6c011e8 100644
--- a/runtime/cha.cc
+++ b/runtime/cha.cc
@@ -19,6 +19,7 @@
#include "art_method-inl.h"
#include "jit/jit.h"
#include "jit/jit_code_cache.h"
+#include "linear_alloc.h"
#include "runtime.h"
#include "scoped_thread_state_change-inl.h"
#include "stack.h"
@@ -581,4 +582,17 @@
}
}
+void ClassHierarchyAnalysis::RemoveDependenciesForLinearAlloc(const LinearAlloc* linear_alloc) {
+ MutexLock mu(Thread::Current(), *Locks::cha_lock_);
+ for (auto it = cha_dependency_map_.begin(); it != cha_dependency_map_.end(); ) {
+ // Use unsafe to avoid locking since the allocator is going to be deleted.
+ if (linear_alloc->ContainsUnsafe(it->first)) {
+ // About to delete the ArtMethod, erase the entry from the map.
+ it = cha_dependency_map_.erase(it);
+ } else {
+ ++it;
+ }
+ }
+}
+
} // namespace art
diff --git a/runtime/cha.h b/runtime/cha.h
index 99224e0..40999dd 100644
--- a/runtime/cha.h
+++ b/runtime/cha.h
@@ -29,6 +29,7 @@
namespace art {
class ArtMethod;
+class LinearAlloc;
/**
* Class Hierarchy Analysis (CHA) tries to devirtualize virtual calls into
@@ -112,6 +113,11 @@
// Update CHA info for methods that `klass` overrides, after loading `klass`.
void UpdateAfterLoadingOf(Handle<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_);
+ // Remove all of the dependencies for a linear allocator. This is called when dex cache unloading
+ // occurs.
+ void RemoveDependenciesForLinearAlloc(const LinearAlloc* linear_alloc)
+ REQUIRES(!Locks::cha_lock_);
+
private:
void InitSingleImplementationFlag(Handle<mirror::Class> klass,
ArtMethod* method,
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index c5e11f1..74c04d1 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -2315,11 +2315,16 @@
JavaVMExt* const vm = runtime->GetJavaVM();
vm->DeleteWeakGlobalRef(self, data.weak_root);
// Notify the JIT that we need to remove the methods and/or profiling info.
+ ClassHierarchyAnalysis* const cha = runtime->GetClassHierarchyAnalysis();
if (runtime->GetJit() != nullptr) {
jit::JitCodeCache* code_cache = runtime->GetJit()->GetCodeCache();
if (code_cache != nullptr) {
+ // For the JIT case, RemoveMethodsIn removes the CHA dependencies.
code_cache->RemoveMethodsIn(self, *data.allocator);
}
+ } else {
+ // If we don't have a JIT, we need to manually remove the CHA dependencies manually.
+ cha->RemoveDependenciesForLinearAlloc(data.allocator);
}
delete data.allocator;
delete data.class_table;