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,