Per-DexFile locking for inliner initialization.

And clean up lock and compiler driver naming.

Change-Id: I1562c7f55c4b0174a36007ba6199360da06169ff
diff --git a/compiler/dex/quick/dex_file_method_inliner.cc b/compiler/dex/quick/dex_file_method_inliner.cc
index b21e37e..ba98225 100644
--- a/compiler/dex/quick/dex_file_method_inliner.cc
+++ b/compiler/dex/quick/dex_file_method_inliner.cc
@@ -16,6 +16,10 @@
 
 #include <algorithm>
 #include "base/macros.h"
+#include "base/mutex.h"
+#include "base/mutex-inl.h"
+#include "thread.h"
+#include "thread-inl.h"
 #include "dex/mir_graph.h"
 
 #include "dex_file_method_inliner.h"
@@ -228,7 +232,8 @@
 };
 
 DexFileMethodInliner::DexFileMethodInliner()
-    : dex_file_(NULL) {
+    : lock_("DexFileMethodInliner lock", kDexFileMethodInlinerLock),
+      dex_file_(NULL) {
   COMPILE_ASSERT(kClassCacheFirst == 0, kClassCacheFirst_not_0);
   COMPILE_ASSERT(arraysize(kClassCacheNames) == kClassCacheLast, bad_arraysize_kClassCacheNames);
   COMPILE_ASSERT(kNameCacheFirst == 0, kNameCacheFirst_not_0);
@@ -240,16 +245,21 @@
 DexFileMethodInliner::~DexFileMethodInliner() {
 }
 
-bool DexFileMethodInliner::IsIntrinsic(uint32_t method_index) const {
+bool DexFileMethodInliner::IsIntrinsic(uint32_t method_index) {
+  ReaderMutexLock mu(Thread::Current(), lock_);
   return intrinsics_.find(method_index) != intrinsics_.end();
 }
 
-bool DexFileMethodInliner::GenIntrinsic(Mir2Lir* backend, CallInfo* info) const {
-  auto it = intrinsics_.find(info->index);
-  if (it == intrinsics_.end()) {
-    return false;
+bool DexFileMethodInliner::GenIntrinsic(Mir2Lir* backend, CallInfo* info) {
+  Intrinsic intrinsic;
+  {
+    ReaderMutexLock mu(Thread::Current(), lock_);
+    auto it = intrinsics_.find(info->index);
+    if (it == intrinsics_.end()) {
+      return false;
+    }
+    intrinsic = it->second;
   }
-  const Intrinsic& intrinsic = it->second;
   switch (intrinsic.opcode) {
     case kIntrinsicDoubleCvt:
       return backend->GenInlinedDoubleCvt(info);
diff --git a/compiler/dex/quick/dex_file_method_inliner.h b/compiler/dex/quick/dex_file_method_inliner.h
index 948f4bb..9198f2a 100644
--- a/compiler/dex/quick/dex_file_method_inliner.h
+++ b/compiler/dex/quick/dex_file_method_inliner.h
@@ -19,6 +19,9 @@
 
 #include <stdint.h>
 #include <map>
+#include "base/mutex.h"
+#include "base/macros.h"
+#include "locks.h"
 
 namespace art {
 
@@ -95,12 +98,12 @@
     /**
      * Check whether a particular method index corresponds to an intrinsic function.
      */
-    bool IsIntrinsic(uint32_t method_index) const;
+    bool IsIntrinsic(uint32_t method_index) LOCKS_EXCLUDED(lock_);
 
     /**
      * Generate code for an intrinsic function invocation.
      */
-    bool GenIntrinsic(Mir2Lir* backend, CallInfo* info) const;
+    bool GenIntrinsic(Mir2Lir* backend, CallInfo* info) LOCKS_EXCLUDED(lock_);
 
   private:
     /**
@@ -300,14 +303,15 @@
      *
      * Only DexFileToMethodInlinerMap may call this function to initialize the inliner.
      */
-    void FindIntrinsics(const DexFile* dex_file);
+    void FindIntrinsics(const DexFile* dex_file) EXCLUSIVE_LOCKS_REQUIRED(lock_);
 
     friend class DexFileToMethodInlinerMap;
 
+    ReaderWriterMutex lock_;
     /*
      * Maps method indexes (for the particular DexFile) to Intrinsic defintions.
      */
-    std::map<uint32_t, Intrinsic> intrinsics_;
+    std::map<uint32_t, Intrinsic> intrinsics_ GUARDED_BY(lock_);
     const DexFile* dex_file_;
 
     DISALLOW_COPY_AND_ASSIGN(DexFileMethodInliner);
diff --git a/compiler/dex/quick/dex_file_to_method_inliner_map.cc b/compiler/dex/quick/dex_file_to_method_inliner_map.cc
index 0107ed3..2fec183 100644
--- a/compiler/dex/quick/dex_file_to_method_inliner_map.cc
+++ b/compiler/dex/quick/dex_file_to_method_inliner_map.cc
@@ -28,7 +28,7 @@
 namespace art {
 
 DexFileToMethodInlinerMap::DexFileToMethodInlinerMap()
-    : lock_("inline_helper_mutex") {
+    : lock_("DexFileToMethodInlinerMap lock", kDexFileToMethodInlinerMapLock) {
 }
 
 DexFileToMethodInlinerMap::~DexFileToMethodInlinerMap() {
@@ -37,26 +37,37 @@
   }
 }
 
-const DexFileMethodInliner& DexFileToMethodInlinerMap::GetMethodInliner(const DexFile* dex_file) {
+DexFileMethodInliner* DexFileToMethodInlinerMap::GetMethodInliner(const DexFile* dex_file) {
   Thread* self = Thread::Current();
   {
-    ReaderMutexLock lock(self, lock_);
+    ReaderMutexLock mu(self, lock_);
     auto it = inliners_.find(dex_file);
     if (it != inliners_.end()) {
-      return *it->second;
+      return it->second;
     }
   }
 
-  WriterMutexLock lock(self, lock_);
-  DexFileMethodInliner** inliner = &inliners_[dex_file];  // inserts new entry if not found
-  if (*inliner) {
-    return **inliner;
+  // We need to acquire our lock_ to modify inliners_ but we want to release it
+  // before we initialize the new inliner. However, we need to acquire the
+  // new inliner's lock_ before we release our lock_ to prevent another thread
+  // from using the uninitialized inliner. This requires explicit calls to
+  // ExclusiveLock()/ExclusiveUnlock() on one of the locks, the other one
+  // can use WriterMutexLock.
+  DexFileMethodInliner* locked_inliner;
+  {
+    WriterMutexLock mu(self, lock_);
+    DexFileMethodInliner** inliner = &inliners_[dex_file];  // inserts new entry if not found
+    if (*inliner) {
+      return *inliner;
+    }
+    *inliner = new DexFileMethodInliner;
+    DCHECK(*inliner != nullptr);
+    locked_inliner = *inliner;
+    locked_inliner->lock_.ExclusiveLock(self);  // Acquire inliner's lock_ before releasing lock_.
   }
-  *inliner = new DexFileMethodInliner();
-  DCHECK(*inliner != nullptr);
-  // TODO: per-dex file locking for the intrinsics container filling.
-  (*inliner)->FindIntrinsics(dex_file);
-  return **inliner;
+  locked_inliner->FindIntrinsics(dex_file);
+  locked_inliner->lock_.ExclusiveUnlock(self);
+  return locked_inliner;
 }
 
 }  // namespace art
diff --git a/compiler/dex/quick/dex_file_to_method_inliner_map.h b/compiler/dex/quick/dex_file_to_method_inliner_map.h
index 476f002..6d5b889 100644
--- a/compiler/dex/quick/dex_file_to_method_inliner_map.h
+++ b/compiler/dex/quick/dex_file_to_method_inliner_map.h
@@ -40,7 +40,7 @@
     DexFileToMethodInlinerMap();
     ~DexFileToMethodInlinerMap();
 
-    const DexFileMethodInliner& GetMethodInliner(const DexFile* dex_file) LOCKS_EXCLUDED(lock_);
+    DexFileMethodInliner* GetMethodInliner(const DexFile* dex_file) LOCKS_EXCLUDED(lock_);
 
   private:
     ReaderWriterMutex lock_;
diff --git a/compiler/dex/quick/gen_invoke.cc b/compiler/dex/quick/gen_invoke.cc
index e66d4ea..ee6f9c8 100644
--- a/compiler/dex/quick/gen_invoke.cc
+++ b/compiler/dex/quick/gen_invoke.cc
@@ -1242,7 +1242,7 @@
     if (inliner_ == nullptr) {
       QuickCompilerContext* context = reinterpret_cast<QuickCompilerContext*>(
           cu_->compiler_driver->GetCompilerContext());
-      inliner_ = &context->GetInlinerMap()->GetMethodInliner(cu_->dex_file);
+      inliner_ = context->GetInlinerMap()->GetMethodInliner(cu_->dex_file);
     }
     if (inliner_->GenIntrinsic(this, info)) {
       return;
diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h
index 2a54eb3..8415cbf 100644
--- a/compiler/dex/quick/mir_to_lir.h
+++ b/compiler/dex/quick/mir_to_lir.h
@@ -827,7 +827,7 @@
     LIR* first_lir_insn_;
     LIR* last_lir_insn_;
     // Lazily retrieved method inliner for intrinsics.
-    const DexFileMethodInliner* inliner_;
+    DexFileMethodInliner* inliner_;
 };  // Class Mir2Lir
 
 }  // namespace art
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 43ed28c..1879a94 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -284,10 +284,10 @@
 };
 
 extern "C" void ArtInitCompilerContext(art::CompilerDriver& driver);
-extern "C" void ArtInitQuickCompilerContext(art::CompilerDriver& compiler);
+extern "C" void ArtInitQuickCompilerContext(art::CompilerDriver& driver);
 
 extern "C" void ArtUnInitCompilerContext(art::CompilerDriver& driver);
-extern "C" void ArtUnInitQuickCompilerContext(art::CompilerDriver& compiler);
+extern "C" void ArtUnInitQuickCompilerContext(art::CompilerDriver& driver);
 
 extern "C" art::CompiledMethod* ArtCompileMethod(art::CompilerDriver& driver,
                                                  const art::DexFile::CodeItem* code_item,
diff --git a/runtime/locks.h b/runtime/locks.h
index 2308e95..72d4f65 100644
--- a/runtime/locks.h
+++ b/runtime/locks.h
@@ -41,6 +41,8 @@
   kRosAllocBracketLock,
   kRosAllocBulkFreeLock,
   kAllocSpaceLock,
+  kDexFileMethodInlinerLock,
+  kDexFileToMethodInlinerMapLock,
   kMarkSweepMarkStackLock,
   kDefaultMutexLevel,
   kMarkSweepLargeObjectLock,