Reduce lock contention when debugging
Uses a ReaderWriterMutex for the breakpoint lock to reduce contention during
debugging session.
Also adds missing thread safety annotations on fields and methods related to
instrumentation and debugging.
Bug: 16814665
Bug: 11667502
(cherry picked from commit 59d9d668d4f4286813afe2b4e7c6db839222ce96)
Change-Id: I5f1156da8c6cc8316d6db16e6cfb2470fe289ad3
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index 9136f9f..eb90696 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -209,7 +209,7 @@
bool need_full_deoptimization_;
};
-static std::ostream& operator<<(std::ostream& os, Breakpoint& rhs)
+static std::ostream& operator<<(std::ostream& os, const Breakpoint& rhs)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
os << StringPrintf("Breakpoint[%s @%#x]", PrettyMethod(rhs.Method()).c_str(), rhs.DexPc());
return os;
@@ -373,7 +373,7 @@
static bool IsBreakpoint(const mirror::ArtMethod* m, uint32_t dex_pc)
LOCKS_EXCLUDED(Locks::breakpoint_lock_)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- MutexLock mu(Thread::Current(), *Locks::breakpoint_lock_);
+ ReaderMutexLock mu(Thread::Current(), *Locks::breakpoint_lock_);
for (size_t i = 0, e = gBreakpoints.size(); i < e; ++i) {
if (gBreakpoints[i].DexPc() == dex_pc && gBreakpoints[i].Method() == m) {
VLOG(jdwp) << "Hit breakpoint #" << i << ": " << gBreakpoints[i];
@@ -740,7 +740,7 @@
{
// TODO: dalvik only warned if there were breakpoints left over. clear in Dbg::Disconnected?
- MutexLock mu(Thread::Current(), *Locks::breakpoint_lock_);
+ ReaderMutexLock mu(Thread::Current(), *Locks::breakpoint_lock_);
CHECK_EQ(gBreakpoints.size(), 0U);
}
@@ -3045,7 +3045,7 @@
}
static const Breakpoint* FindFirstBreakpointForMethod(mirror::ArtMethod* m)
- EXCLUSIVE_LOCKS_REQUIRED(Locks::breakpoint_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_, Locks::breakpoint_lock_) {
for (Breakpoint& breakpoint : gBreakpoints) {
if (breakpoint.Method() == m) {
return &breakpoint;
@@ -3056,7 +3056,7 @@
// Sanity checks all existing breakpoints on the same method.
static void SanityCheckExistingBreakpoints(mirror::ArtMethod* m, bool need_full_deoptimization)
- EXCLUSIVE_LOCKS_REQUIRED(Locks::breakpoint_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_, Locks::breakpoint_lock_) {
if (kIsDebugBuild) {
for (const Breakpoint& breakpoint : gBreakpoints) {
CHECK_EQ(need_full_deoptimization, breakpoint.NeedFullDeoptimization());
@@ -3081,7 +3081,7 @@
mirror::ArtMethod* m = FromMethodId(location->method_id);
DCHECK(m != nullptr) << "No method for method id " << location->method_id;
- MutexLock mu(self, *Locks::breakpoint_lock_);
+ WriterMutexLock mu(self, *Locks::breakpoint_lock_);
const Breakpoint* const existing_breakpoint = FindFirstBreakpointForMethod(m);
bool need_full_deoptimization;
if (existing_breakpoint == nullptr) {
@@ -3112,7 +3112,7 @@
// Uninstalls a breakpoint at the specified location. Also indicates through the deoptimization
// request if we need to undeoptimize.
void Dbg::UnwatchLocation(const JDWP::JdwpLocation* location, DeoptimizationRequest* req) {
- MutexLock mu(Thread::Current(), *Locks::breakpoint_lock_);
+ WriterMutexLock mu(Thread::Current(), *Locks::breakpoint_lock_);
mirror::ArtMethod* m = FromMethodId(location->method_id);
DCHECK(m != nullptr) << "No method for method id " << location->method_id;
bool need_full_deoptimization = false;