Change ClassLinker::dex_caches_ from list to unordered_map.
Move the DexFile* pointer from struct field out to map key.
This makes it easy and fast to find DexCache from DexFile.
Add check that given DexFile* is registered only once.
Test: test.py -b -r --host --64
Test: generated images are identical as before
Change-Id: I84a6d6cbf963af2408abe5bb5e4c99d0ca11df78
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 2ce0294..4d1589b 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -3894,14 +3894,14 @@
bool initialize_oat_file_data = (oat_file != nullptr) && oat_file->IsExecutable();
JavaVMExt* const vm = self->GetJniEnv()->GetVm();
for (auto it = dex_caches_.begin(); it != dex_caches_.end(); ) {
- DexCacheData data = *it;
+ const DexCacheData& data = it->second;
if (self->IsJWeakCleared(data.weak_root)) {
vm->DeleteWeakGlobalRef(self, data.weak_root);
it = dex_caches_.erase(it);
} else {
if (initialize_oat_file_data &&
- it->dex_file->GetOatDexFile() != nullptr &&
- it->dex_file->GetOatDexFile()->GetOatFile() == oat_file) {
+ it->first->GetOatDexFile() != nullptr &&
+ it->first->GetOatDexFile()->GetOatFile() == oat_file) {
initialize_oat_file_data = false; // Already initialized.
}
++it;
@@ -3916,9 +3916,8 @@
jweak dex_cache_jweak = vm->AddWeakGlobalRef(self, dex_cache);
DexCacheData data;
data.weak_root = dex_cache_jweak;
- data.dex_file = dex_cache->GetDexFile();
data.class_table = ClassTableForClassLoader(class_loader);
- AddNativeDebugInfoForDex(self, data.dex_file);
+ AddNativeDebugInfoForDex(self, &dex_file);
DCHECK(data.class_table != nullptr);
// Make sure to hold the dex cache live in the class table. This case happens for the boot class
// path dex caches without an image.
@@ -3930,7 +3929,8 @@
// remembered sets and generational GCs.
WriteBarrier::ForEveryFieldWrite(class_loader);
}
- dex_caches_.push_back(data);
+ bool inserted = dex_caches_.emplace(&dex_file, std::move(data)).second;
+ CHECK(inserted);
}
ObjPtr<mirror::DexCache> ClassLinker::DecodeDexCacheLocked(Thread* self, const DexCacheData* data) {
@@ -3944,7 +3944,7 @@
const DexCacheData* data,
ObjPtr<mirror::ClassLoader> class_loader) {
CHECK(data != nullptr);
- DCHECK_EQ(dex_cache->GetDexFile(), data->dex_file);
+ DCHECK_EQ(FindDexCacheDataLocked(*dex_cache->GetDexFile()), data);
return data->class_table == ClassTableForClassLoader(class_loader);
}
@@ -4089,13 +4089,14 @@
return dex_cache;
}
// Failure, dump diagnostic and abort.
- for (const DexCacheData& data : dex_caches_) {
+ for (const auto& entry : dex_caches_) {
+ const DexCacheData& data = entry.second;
if (DecodeDexCacheLocked(self, &data) != nullptr) {
- LOG(FATAL_WITHOUT_ABORT) << "Registered dex file " << data.dex_file->GetLocation();
+ LOG(FATAL_WITHOUT_ABORT) << "Registered dex file " << entry.first->GetLocation();
}
}
LOG(FATAL) << "Failed to find DexCache for DexFile " << dex_file.GetLocation()
- << " " << &dex_file << " " << dex_cache_data->dex_file;
+ << " " << &dex_file;
UNREACHABLE();
}
@@ -4103,29 +4104,21 @@
const DexFile* dex_file = dex_cache->GetDexFile();
DCHECK(dex_file != nullptr);
ReaderMutexLock mu(self, *Locks::dex_lock_);
- // Search assuming unique-ness of dex file.
- for (const DexCacheData& data : dex_caches_) {
- // Avoid decoding (and read barriers) other unrelated dex caches.
- if (data.dex_file == dex_file) {
- ObjPtr<mirror::DexCache> registered_dex_cache = DecodeDexCacheLocked(self, &data);
- if (registered_dex_cache != nullptr) {
- CHECK_EQ(registered_dex_cache, dex_cache) << dex_file->GetLocation();
- return data.class_table;
- }
+ auto it = dex_caches_.find(dex_file);
+ if (it != dex_caches_.end()) {
+ const DexCacheData& data = it->second;
+ ObjPtr<mirror::DexCache> registered_dex_cache = DecodeDexCacheLocked(self, &data);
+ if (registered_dex_cache != nullptr) {
+ CHECK_EQ(registered_dex_cache, dex_cache) << dex_file->GetLocation();
+ return data.class_table;
}
}
return nullptr;
}
const ClassLinker::DexCacheData* ClassLinker::FindDexCacheDataLocked(const DexFile& dex_file) {
- // Search assuming unique-ness of dex file.
- for (const DexCacheData& data : dex_caches_) {
- // Avoid decoding (and read barriers) other unrelated dex caches.
- if (data.dex_file == &dex_file) {
- return &data;
- }
- }
- return nullptr;
+ auto it = dex_caches_.find(&dex_file);
+ return it != dex_caches_.end() ? &it->second : nullptr;
}
void ClassLinker::CreatePrimitiveClass(Thread* self,
@@ -9754,13 +9747,14 @@
if (loader != nullptr) {
os << "#" << class_loader_index++ << " " << loader->GetClass()->PrettyDescriptor() << ": [";
bool saw_one_dex_file = false;
- for (const DexCacheData& dex_cache : dex_caches_) {
- if (dex_cache.IsValid() && dex_cache.class_table == class_loader.class_table) {
+ for (const auto& entry : dex_caches_) {
+ const DexCacheData& dex_cache = entry.second;
+ if (dex_cache.class_table == class_loader.class_table) {
if (saw_one_dex_file) {
os << ":";
}
saw_one_dex_file = true;
- os << dex_cache.dex_file->GetLocation();
+ os << entry.first->GetLocation();
}
}
os << "]";