summaryrefslogtreecommitdiff
path: root/runtime/class_linker.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/class_linker.cc')
-rw-r--r--runtime/class_linker.cc46
1 files changed, 44 insertions, 2 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 6480dfd249..dfe6257b0f 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -3884,7 +3884,8 @@ void ClassLinker::RegisterDexFileLocked(const DexFile& dex_file,
std::string dex_file_location = dex_file.GetLocation();
// The following paths checks don't work on preopt when using boot dex files, where the dex
// cache location is the one on device, and the dex_file's location is the one on host.
- if (!(Runtime::Current()->IsAotCompiler() && class_loader == nullptr && !kIsTargetBuild)) {
+ Runtime* runtime = Runtime::Current();
+ if (!(runtime->IsAotCompiler() && class_loader == nullptr && !kIsTargetBuild)) {
CHECK_GE(dex_file_location.length(), dex_cache_length)
<< dex_cache_location << " " << dex_file.GetLocation();
const std::string dex_file_suffix = dex_file_location.substr(
@@ -3896,7 +3897,7 @@ void ClassLinker::RegisterDexFileLocked(const DexFile& dex_file,
}
// Check if we need to initialize OatFile data (.data.bimg.rel.ro and .bss
- // sections) needed for code execution.
+ // sections) needed for code execution and register the oat code range.
const OatFile* oat_file =
(dex_file.GetOatDexFile() != nullptr) ? dex_file.GetOatDexFile()->GetOatFile() : nullptr;
bool initialize_oat_file_data = (oat_file != nullptr) && oat_file->IsExecutable();
@@ -3912,6 +3913,13 @@ void ClassLinker::RegisterDexFileLocked(const DexFile& dex_file,
}
if (initialize_oat_file_data) {
oat_file->InitializeRelocations();
+ // Notify the fault handler about the new executable code range if needed.
+ size_t exec_offset = oat_file->GetOatHeader().GetExecutableOffset();
+ DCHECK_LE(exec_offset, oat_file->Size());
+ size_t exec_size = oat_file->Size() - exec_offset;
+ if (exec_size != 0u) {
+ runtime->AddGeneratedCodeRange(oat_file->Begin() + exec_offset, exec_size);
+ }
}
// Let hiddenapi assign a domain to the newly registered dex file.
@@ -10334,16 +10342,23 @@ void ClassLinker::CleanupClassLoaders() {
}
}
}
+ std::set<const OatFile*> unregistered_oat_files;
if (!to_delete.empty()) {
JavaVMExt* vm = self->GetJniEnv()->GetVm();
WriterMutexLock mu(self, *Locks::dex_lock_);
for (auto it = dex_caches_.begin(), end = dex_caches_.end(); it != end; ) {
+ const DexFile* dex_file = it->first;
const DexCacheData& data = it->second;
if (self->DecodeJObject(data.weak_root) == nullptr) {
DCHECK(to_delete.end() != std::find_if(
to_delete.begin(),
to_delete.end(),
[&](const ClassLoaderData& cld) { return cld.class_table == data.class_table; }));
+ if (dex_file->GetOatDexFile() != nullptr &&
+ dex_file->GetOatDexFile()->GetOatFile() != nullptr &&
+ dex_file->GetOatDexFile()->GetOatFile()->IsExecutable()) {
+ unregistered_oat_files.insert(dex_file->GetOatDexFile()->GetOatFile());
+ }
vm->DeleteWeakGlobalRef(self, data.weak_root);
it = dex_caches_.erase(it);
} else {
@@ -10355,6 +10370,33 @@ void ClassLinker::CleanupClassLoaders() {
// CHA unloading analysis and SingleImplementaion cleanups are required.
DeleteClassLoader(self, data, /*cleanup_cha=*/ true);
}
+ if (!unregistered_oat_files.empty()) {
+ // Removing the code range requires running an empty checkpoint and we cannot do
+ // that while holding the mutator lock. This thread is not currently `Runnable`
+ // for CC GC, so we need explicit unlock/lock instead of `ScopedThreadStateChange`.
+ // TODO: Clean up state transition in CC GC and possibly other GC types. b/259440389
+ bool runnable = (self->GetState() == ThreadState::kRunnable);
+ if (runnable) {
+ self->TransitionFromRunnableToSuspended(ThreadState::kNative);
+ } else {
+ Locks::mutator_lock_->SharedUnlock(self);
+ }
+ for (const OatFile* oat_file : unregistered_oat_files) {
+ // Notify the fault handler about removal of the executable code range if needed.
+ DCHECK(oat_file->IsExecutable());
+ size_t exec_offset = oat_file->GetOatHeader().GetExecutableOffset();
+ DCHECK_LE(exec_offset, oat_file->Size());
+ size_t exec_size = oat_file->Size() - exec_offset;
+ if (exec_size != 0u) {
+ Runtime::Current()->RemoveGeneratedCodeRange(oat_file->Begin() + exec_offset, exec_size);
+ }
+ }
+ if (runnable) {
+ self->TransitionFromSuspendedToRunnable();
+ } else {
+ Locks::mutator_lock_->SharedLock(self);
+ }
+ }
}
class ClassLinker::FindVirtualMethodHolderVisitor : public ClassVisitor {