Add lock around interpreter string init reg map.
Fixes intermittent test failures. Note that locks can't be held
while the verifier is generating the map.
Change-Id: Ie38d6bf0d9c5e81d66b8c167fde0e75a0565cea5
diff --git a/runtime/base/mutex.cc b/runtime/base/mutex.cc
index 62cfb52..b2c5677 100644
--- a/runtime/base/mutex.cc
+++ b/runtime/base/mutex.cc
@@ -43,6 +43,7 @@
ReaderWriterMutex* Locks::heap_bitmap_lock_ = nullptr;
Mutex* Locks::instrument_entrypoints_lock_ = nullptr;
Mutex* Locks::intern_table_lock_ = nullptr;
+Mutex* Locks::interpreter_string_init_map_lock_ = nullptr;
Mutex* Locks::jni_libraries_lock_ = nullptr;
Mutex* Locks::logging_lock_ = nullptr;
Mutex* Locks::mem_maps_lock_ = nullptr;
@@ -992,6 +993,10 @@
DCHECK(alloc_tracker_lock_ == nullptr);
alloc_tracker_lock_ = new Mutex("AllocTracker lock", current_lock_level);
+ UPDATE_CURRENT_LOCK_LEVEL(kInterpreterStringInitMapLock);
+ DCHECK(interpreter_string_init_map_lock_ == nullptr);
+ interpreter_string_init_map_lock_ = new Mutex("Interpreter String initializer reference map lock", current_lock_level);
+
UPDATE_CURRENT_LOCK_LEVEL(kThreadListLock);
DCHECK(thread_list_lock_ == nullptr);
thread_list_lock_ = new Mutex("thread list lock", current_lock_level);
diff --git a/runtime/base/mutex.h b/runtime/base/mutex.h
index 6bf203c..3da806b 100644
--- a/runtime/base/mutex.h
+++ b/runtime/base/mutex.h
@@ -99,6 +99,7 @@
kMonitorListLock,
kJniLoadLibraryLock,
kThreadListLock,
+ kInterpreterStringInitMapLock,
kAllocTrackerLock,
kDeoptimizationLock,
kProfilerLock,
@@ -612,9 +613,12 @@
// TODO: improve name, perhaps instrumentation_update_lock_.
static Mutex* deoptimization_lock_ ACQUIRED_AFTER(alloc_tracker_lock_);
+ // Guards String initializer register map in interpreter.
+ static Mutex* interpreter_string_init_map_lock_ ACQUIRED_AFTER(deoptimization_lock_);
+
// The thread_list_lock_ guards ThreadList::list_. It is also commonly held to stop threads
// attaching and detaching.
- static Mutex* thread_list_lock_ ACQUIRED_AFTER(deoptimization_lock_);
+ static Mutex* thread_list_lock_ ACQUIRED_AFTER(interpreter_string_init_map_lock_);
// Signaled when threads terminate. Used to determine when all non-daemons have terminated.
static ConditionVariable* thread_exit_cond_ GUARDED_BY(Locks::thread_list_lock_);
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index 6602840..02ec90c 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -699,10 +699,17 @@
SafeMap<uint32_t, std::set<uint32_t>> string_init_map;
SafeMap<uint32_t, std::set<uint32_t>>* string_init_map_ptr;
MethodRefToStringInitRegMap& method_to_string_init_map = Runtime::Current()->GetStringInitMap();
- auto it = method_to_string_init_map.find(method_ref);
+ MethodRefToStringInitRegMap::iterator it;
+ {
+ MutexLock mu(self, *Locks::interpreter_string_init_map_lock_);
+ it = method_to_string_init_map.find(method_ref);
+ }
if (it == method_to_string_init_map.end()) {
string_init_map = std::move(verifier::MethodVerifier::FindStringInitMap(method));
- method_to_string_init_map.Overwrite(method_ref, string_init_map);
+ {
+ MutexLock mu(self, *Locks::interpreter_string_init_map_lock_);
+ method_to_string_init_map.Overwrite(method_ref, string_init_map);
+ }
string_init_map_ptr = &string_init_map;
} else {
string_init_map_ptr = &it->second;