OSDN Git Service

Add lock around interpreter string init reg map.
authorJeff Hao <jeffhao@google.com>
Fri, 18 Sep 2015 00:29:01 +0000 (17:29 -0700)
committerJeff Hao <jeffhao@google.com>
Fri, 18 Sep 2015 01:33:16 +0000 (18:33 -0700)
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
runtime/base/mutex.h
runtime/interpreter/interpreter_common.cc

index 62cfb52..b2c5677 100644 (file)
@@ -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);
index 6bf203c..3da806b 100644 (file)
@@ -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_);
index 6602840..02ec90c 100644 (file)
@@ -699,10 +699,17 @@ static inline bool DoCallCommon(ArtMethod* called_method,
     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;