Add atomic method reference map
Less RAM usage and faster than using a normal map with
MethodReference. Speed is faster by avoiding locking and tree
traversal. RAM usage is lower since the map usually had a value
for most method references.
Plan on using for marking methods for dex2dex, storing compiled
methods. Also use the new map for VerifiedMethods (refactoring).
Added test.
Bug: 32641252
Test: test-art-host-run-test
Change-Id: I46268031b8e0daf9be3597145cf6ecf579a039e2
diff --git a/compiler/dex/verification_results.cc b/compiler/dex/verification_results.cc
index 3fb10d8..669d8cd 100644
--- a/compiler/dex/verification_results.cc
+++ b/compiler/dex/verification_results.cc
@@ -23,6 +23,7 @@
#include "driver/compiler_options.h"
#include "thread.h"
#include "thread-inl.h"
+#include "utils/atomic_method_ref_map-inl.h"
#include "verified_method.h"
#include "verifier/method_verifier-inl.h"
@@ -35,8 +36,11 @@
VerificationResults::~VerificationResults() {
WriterMutexLock mu(Thread::Current(), verified_methods_lock_);
- DeleteResults(preregistered_dex_files_);
STLDeleteValues(&verified_methods_);
+ atomic_verified_methods_.Visit([](const MethodReference& ref ATTRIBUTE_UNUSED,
+ const VerifiedMethod* method) {
+ delete method;
+ });
}
void VerificationResults::ProcessVerifiedMethod(verifier::MethodVerifier* method_verifier) {
@@ -49,16 +53,17 @@
// We'll punt this later.
return;
}
- bool inserted;
- DexFileMethodArray* const array = GetMethodArray(ref.dex_file);
+ AtomicMap::InsertResult result = atomic_verified_methods_.Insert(ref,
+ /*expected*/ nullptr,
+ verified_method.get());
const VerifiedMethod* existing = nullptr;
- if (array != nullptr) {
- DCHECK(array != nullptr);
- Atomic<const VerifiedMethod*>* slot = &(*array)[ref.dex_method_index];
- inserted = slot->CompareExchangeStrongSequentiallyConsistent(nullptr, verified_method.get());
+ bool inserted;
+ if (result != AtomicMap::kInsertResultInvalidDexFile) {
+ inserted = (result == AtomicMap::kInsertResultSuccess);
if (!inserted) {
- existing = slot->LoadSequentiallyConsistent();
- DCHECK_NE(verified_method.get(), existing);
+ // Rare case.
+ CHECK(atomic_verified_methods_.Get(ref, &existing));
+ CHECK_NE(verified_method.get(), existing);
}
} else {
WriterMutexLock mu(Thread::Current(), verified_methods_lock_);
@@ -89,9 +94,9 @@
}
const VerifiedMethod* VerificationResults::GetVerifiedMethod(MethodReference ref) {
- DexFileMethodArray* array = GetMethodArray(ref.dex_file);
- if (array != nullptr) {
- return (*array)[ref.dex_method_index].LoadRelaxed();
+ const VerifiedMethod* ret = nullptr;
+ if (atomic_verified_methods_.Get(ref, &ret)) {
+ return ret;
}
ReaderMutexLock mu(Thread::Current(), verified_methods_lock_);
auto it = verified_methods_.find(ref);
@@ -124,10 +129,8 @@
return true;
}
-void VerificationResults::PreRegisterDexFile(const DexFile* dex_file) {
- CHECK(preregistered_dex_files_.find(dex_file) == preregistered_dex_files_.end())
- << dex_file->GetLocation();
- DexFileMethodArray array(dex_file->NumMethodIds());
+void VerificationResults::AddDexFile(const DexFile* dex_file) {
+ atomic_verified_methods_.AddDexFile(dex_file);
WriterMutexLock mu(Thread::Current(), verified_methods_lock_);
// There can be some verified methods that are already registered for the dex_file since we set
// up well known classes earlier. Remove these and put them in the array so that we don't
@@ -135,31 +138,13 @@
for (auto it = verified_methods_.begin(); it != verified_methods_.end(); ) {
MethodReference ref = it->first;
if (ref.dex_file == dex_file) {
- array[ref.dex_method_index].StoreSequentiallyConsistent(it->second);
+ CHECK(atomic_verified_methods_.Insert(ref, nullptr, it->second) ==
+ AtomicMap::kInsertResultSuccess);
it = verified_methods_.erase(it);
} else {
++it;
}
}
- preregistered_dex_files_.emplace(dex_file, std::move(array));
-}
-
-void VerificationResults::DeleteResults(DexFileResults& array) {
- for (auto& pair : array) {
- for (Atomic<const VerifiedMethod*>& method : pair.second) {
- delete method.LoadSequentiallyConsistent();
- }
- }
- array.clear();
-}
-
-VerificationResults::DexFileMethodArray* VerificationResults::GetMethodArray(
- const DexFile* dex_file) {
- auto it = preregistered_dex_files_.find(dex_file);
- if (it != preregistered_dex_files_.end()) {
- return &it->second;
- }
- return nullptr;
}
} // namespace art