Use a per-thread VerifierDeps.
Avoid lock contention on a singleton VerifierDeps by allocating
temporary per-thread VerifierDeps that get merged after verification.
This saves around ~35% compile-times on interpret-only.
Only the creation of extra strings is guarded by a lock, for simplicity.
Test: test-art-host, test-art-target
bug: 32641252
bug: 30937355
Change-Id: I11a2367da882b58e39afa7b42cba2e74a209b75d
diff --git a/compiler/verifier_deps_test.cc b/compiler/verifier_deps_test.cc
index 03d3f4e..dcf3619 100644
--- a/compiler/verifier_deps_test.cc
+++ b/compiler/verifier_deps_test.cc
@@ -154,6 +154,7 @@
}
CHECK(method != nullptr);
+ Thread::Current()->SetVerifierDeps(callbacks_->GetVerifierDeps());
MethodVerifier verifier(Thread::Current(),
primary_dex_file_,
dex_cache_handle,
@@ -169,6 +170,7 @@
false /* verify to dump */,
true /* allow_thread_suspension */);
verifier.Verify();
+ Thread::Current()->SetVerifierDeps(nullptr);
return !verifier.HasFailures();
}
@@ -230,7 +232,6 @@
const DexFile::TypeId* type_id = primary_dex_file_->FindTypeId(cls.c_str());
DCHECK(type_id != nullptr);
dex::TypeIndex index = primary_dex_file_->GetIndexForTypeId(*type_id);
- MutexLock mu(Thread::Current(), *Locks::verifier_deps_lock_);
for (const auto& dex_dep : verifier_deps_->dex_deps_) {
for (dex::TypeIndex entry : dex_dep.second->unverified_classes_) {
if (index == entry) {
@@ -246,7 +247,6 @@
bool HasAssignable(const std::string& expected_destination,
const std::string& expected_source,
bool expected_is_assignable) {
- MutexLock mu(Thread::Current(), *Locks::verifier_deps_lock_);
for (auto& dex_dep : verifier_deps_->dex_deps_) {
const DexFile& dex_file = *dex_dep.first;
auto& storage = expected_is_assignable ? dex_dep.second->assignable_types_
@@ -268,7 +268,6 @@
bool HasClass(const std::string& expected_klass,
bool expected_resolved,
const std::string& expected_access_flags = "") {
- MutexLock mu(Thread::Current(), *Locks::verifier_deps_lock_);
for (auto& dex_dep : verifier_deps_->dex_deps_) {
for (auto& entry : dex_dep.second->classes_) {
if (expected_resolved != entry.IsResolved()) {
@@ -303,7 +302,6 @@
bool expected_resolved,
const std::string& expected_access_flags = "",
const std::string& expected_decl_klass = "") {
- MutexLock mu(Thread::Current(), *Locks::verifier_deps_lock_);
for (auto& dex_dep : verifier_deps_->dex_deps_) {
for (auto& entry : dex_dep.second->fields_) {
if (expected_resolved != entry.IsResolved()) {
@@ -357,7 +355,6 @@
bool expected_resolved,
const std::string& expected_access_flags = "",
const std::string& expected_decl_klass = "") {
- MutexLock mu(Thread::Current(), *Locks::verifier_deps_lock_);
for (auto& dex_dep : verifier_deps_->dex_deps_) {
auto& storage = (expected_kind == "direct") ? dex_dep.second->direct_methods_
: (expected_kind == "virtual") ? dex_dep.second->virtual_methods_
@@ -406,13 +403,10 @@
}
size_t NumberOfCompiledDexFiles() {
- MutexLock mu(Thread::Current(), *Locks::verifier_deps_lock_);
return verifier_deps_->dex_deps_.size();
}
size_t HasEachKindOfRecord() {
- MutexLock mu(Thread::Current(), *Locks::verifier_deps_lock_);
-
bool has_strings = false;
bool has_assignability = false;
bool has_classes = false;
@@ -463,8 +457,6 @@
ScopedObjectAccess soa(Thread::Current());
LoadDexFile(&soa);
- MutexLock mu(Thread::Current(), *Locks::verifier_deps_lock_);
-
uint32_t id_Main1 = verifier_deps_->GetIdFromString(*primary_dex_file_, "LMain;");
ASSERT_LT(id_Main1, primary_dex_file_->NumStringIds());
ASSERT_EQ("LMain;", verifier_deps_->GetStringFromId(*primary_dex_file_, id_Main1));