From a2c38644d96cbad4106c0165811d0f670d6cec8f Mon Sep 17 00:00:00 2001 From: Jeff Hao Date: Thu, 17 Sep 2015 17:29:01 -0700 Subject: [PATCH] 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 --- runtime/base/mutex.cc | 5 +++++ runtime/base/mutex.h | 6 +++++- runtime/interpreter/interpreter_common.cc | 11 +++++++++-- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/runtime/base/mutex.cc b/runtime/base/mutex.cc index 62cfb5243..b2c567760 100644 --- a/runtime/base/mutex.cc +++ b/runtime/base/mutex.cc @@ -43,6 +43,7 @@ Mutex* Locks::deoptimization_lock_ = nullptr; 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 @@ void Locks::Init() { 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 6bf203c30..3da806b54 100644 --- a/runtime/base/mutex.h +++ b/runtime/base/mutex.h @@ -99,6 +99,7 @@ enum LockLevel { kMonitorListLock, kJniLoadLibraryLock, kThreadListLock, + kInterpreterStringInitMapLock, kAllocTrackerLock, kDeoptimizationLock, kProfilerLock, @@ -612,9 +613,12 @@ class Locks { // 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 6602840ed..02ec90c78 100644 --- a/runtime/interpreter/interpreter_common.cc +++ b/runtime/interpreter/interpreter_common.cc @@ -699,10 +699,17 @@ static inline bool DoCallCommon(ArtMethod* called_method, SafeMap> string_init_map; SafeMap>* 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; -- 2.11.0