summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Mathieu Chartier <mathieuc@google.com> 2017-07-21 11:17:57 -0700
committer Mathieu Chartier <mathieuc@google.com> 2017-07-24 20:00:57 -0700
commitcf79cf51feeea395a965c8dc452f86be60c00aab (patch)
tree59cb7c7b75a8dd2dfd74cb3002601e032e008892
parentacae6dbe80d07a26a973587b6f838198e13e66c3 (diff)
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
-rw-r--r--runtime/cha.cc14
-rw-r--r--runtime/cha.h6
-rw-r--r--runtime/class_linker.cc5
3 files changed, 25 insertions, 0 deletions
diff --git a/runtime/cha.cc b/runtime/cha.cc
index 8eeebf30ed..6c011e8e39 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::InvalidateSingleImplementationMethods(
}
}
+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 99224e052b..40999dd15b 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 @@ class ClassHierarchyAnalysis {
// 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 c5e11f134e..74c04d19b6 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -2315,11 +2315,16 @@ void ClassLinker::DeleteClassLoader(Thread* self, const ClassLoaderData& data) {
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;