Remove dex file index building mutex.
First thread to get to max misses builds the index and sets an atomic, other
threads continue and return null. Avoids lock contention and removes a member
variable.
Change-Id: Ia91e4a8fd915941aea849f019c85b67894ec6e71
diff --git a/runtime/dex_file.cc b/runtime/dex_file.cc
index 8656bd3..6ef62c5 100644
--- a/runtime/dex_file.cc
+++ b/runtime/dex_file.cc
@@ -354,8 +354,7 @@
proto_ids_(reinterpret_cast<const ProtoId*>(base + header_->proto_ids_off_)),
class_defs_(reinterpret_cast<const ClassDef*>(base + header_->class_defs_off_)),
find_class_def_misses_(0),
- class_def_index_(nullptr),
- build_class_def_index_mutex_("DexFile index creation mutex") {
+ class_def_index_(nullptr) {
CHECK(begin_ != NULL) << GetLocation();
CHECK_GT(size_, 0U) << GetLocation();
}
@@ -444,20 +443,21 @@
// up. This isn't done eagerly at construction as construction is not performed in multi-threaded
// sections of tools like dex2oat. If we're lazy we hopefully increase the chance of balancing
// out which thread builds the index.
- find_class_def_misses_++;
const uint32_t kMaxFailedDexClassDefLookups = 100;
- if (find_class_def_misses_ > kMaxFailedDexClassDefLookups) {
- MutexLock mu(Thread::Current(), build_class_def_index_mutex_);
- // Are we the first ones building the index?
- if (class_def_index_.LoadSequentiallyConsistent() == nullptr) {
- index = new Index(num_class_defs);
- for (uint32_t i = 0; i < num_class_defs; ++i) {
- const ClassDef& class_def = GetClassDef(i);
- const char* descriptor = GetClassDescriptor(class_def);
- index->insert(std::make_pair(descriptor, &class_def));
- }
- class_def_index_.StoreSequentiallyConsistent(index);
+ uint32_t old_misses = find_class_def_misses_.FetchAndAddSequentiallyConsistent(1);
+ if (old_misses == kMaxFailedDexClassDefLookups) {
+ // Are we the ones moving the miss count past the max? Sanity check the index doesn't exist.
+ CHECK(class_def_index_.LoadSequentiallyConsistent() == nullptr);
+ // Build the index.
+ index = new Index(num_class_defs);
+ for (uint32_t i = 0; i < num_class_defs; ++i) {
+ const ClassDef& class_def = GetClassDef(i);
+ const char* descriptor = GetClassDescriptor(class_def);
+ index->insert(std::make_pair(descriptor, &class_def));
}
+ // Sanity check the index still doesn't exist, only 1 thread should build it.
+ CHECK(class_def_index_.LoadSequentiallyConsistent() == nullptr);
+ class_def_index_.StoreSequentiallyConsistent(index);
}
return nullptr;
}
diff --git a/runtime/dex_file.h b/runtime/dex_file.h
index 1b46a12..1cec264 100644
--- a/runtime/dex_file.h
+++ b/runtime/dex_file.h
@@ -979,7 +979,6 @@
};
typedef std::unordered_map<const char*, const ClassDef*, UTF16HashCmp, UTF16HashCmp> Index;
mutable Atomic<Index*> class_def_index_;
- mutable Mutex build_class_def_index_mutex_ DEFAULT_MUTEX_ACQUIRED_AFTER;
};
std::ostream& operator<<(std::ostream& os, const DexFile& dex_file);