Some fixes for JDWP with the interpreter.

- GetStackDepth checks if the thread is suspended, unless the thread is
  itself.
- Scoped the breakpoints lock during UpdateDebugger to prevent it being
  held during PostLocationEvent.
- Removed locking of breakpoints lock in DebugCallbackContext since it's
  already holding it.
- Added level for breakpoints lock to prevent lock level violations.

Change-Id: I3588c9696bb57ada3c8c64dc1d95ae23cdf2b107
diff --git a/src/debugger.cc b/src/debugger.cc
index 87e9c72..5a9faa6 100644
--- a/src/debugger.cc
+++ b/src/debugger.cc
@@ -177,13 +177,13 @@
 static size_t gAllocRecordCount GUARDED_BY(gAllocTrackerLock) = 0;
 
 // Breakpoints and single-stepping.
-static Mutex gBreakpointsLock DEFAULT_MUTEX_ACQUIRED_AFTER ("breakpoints lock");
-static std::vector<Breakpoint> gBreakpoints GUARDED_BY(gBreakpointsLock);
-static SingleStepControl gSingleStepControl GUARDED_BY(gBreakpointsLock);
+static std::vector<Breakpoint> gBreakpoints GUARDED_BY(Locks::breakpoint_lock_);
+static SingleStepControl gSingleStepControl GUARDED_BY(Locks::breakpoint_lock_);
 
 static bool IsBreakpoint(AbstractMethod* m, uint32_t dex_pc)
+    LOCKS_EXCLUDED(Locks::breakpoint_lock_)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  MutexLock mu(Thread::Current(), gBreakpointsLock);
+  MutexLock mu(Thread::Current(), *Locks::breakpoint_lock_);
   for (size_t i = 0; i < gBreakpoints.size(); ++i) {
     if (gBreakpoints[i].method == m && gBreakpoints[i].dex_pc == dex_pc) {
       VLOG(jdwp) << "Hit breakpoint #" << i << ": " << gBreakpoints[i];
@@ -508,7 +508,7 @@
 
   {
     // TODO: dalvik only warned if there were breakpoints left over. clear in Dbg::Disconnected?
-    MutexLock mu(Thread::Current(), gBreakpointsLock);
+    MutexLock mu(Thread::Current(), *Locks::breakpoint_lock_);
     CHECK_EQ(gBreakpoints.size(), 0U);
   }
 
@@ -1572,7 +1572,7 @@
 
   if (kIsDebugBuild) {
     MutexLock mu(Thread::Current(), *Locks::thread_suspend_count_lock_);
-    CHECK(thread->IsSuspended());
+    CHECK(thread == Thread::Current() || thread->IsSuspended());
   }
   CountStackDepthVisitor visitor(thread->GetManagedStack(), thread->GetInstrumentationStack());
   visitor.WalkStack();
@@ -2065,63 +2065,63 @@
     event_flags |= kBreakpoint;
   }
 
-  // If the debugger is single-stepping one of our threads, check to
-  // see if we're that thread and we've reached a step point.
-  MutexLock mu(Thread::Current(), gBreakpointsLock);
-  if (gSingleStepControl.is_active && gSingleStepControl.thread == self) {
-    CHECK(!m->IsNative());
-    if (gSingleStepControl.step_depth == JDWP::SD_INTO) {
-      // Step into method calls.  We break when the line number
-      // or method pointer changes.  If we're in SS_MIN mode, we
-      // always stop.
-      if (gSingleStepControl.method != m) {
-        event_flags |= kSingleStep;
-        VLOG(jdwp) << "SS new method";
-      } else if (gSingleStepControl.step_size == JDWP::SS_MIN) {
-        event_flags |= kSingleStep;
-        VLOG(jdwp) << "SS new instruction";
-      } else if (gSingleStepControl.dex_pcs.find(dex_pc) == gSingleStepControl.dex_pcs.end()) {
-        event_flags |= kSingleStep;
-        VLOG(jdwp) << "SS new line";
-      }
-    } else if (gSingleStepControl.step_depth == JDWP::SD_OVER) {
-      // Step over method calls.  We break when the line number is
-      // different and the frame depth is <= the original frame
-      // depth.  (We can't just compare on the method, because we
-      // might get unrolled past it by an exception, and it's tricky
-      // to identify recursion.)
-
-      // TODO: can we just use the value of 'sp'?
-      int stack_depth = GetStackDepth(self);
-
-      if (stack_depth < gSingleStepControl.stack_depth) {
-        // popped up one or more frames, always trigger
-        event_flags |= kSingleStep;
-        VLOG(jdwp) << "SS method pop";
-      } else if (stack_depth == gSingleStepControl.stack_depth) {
-        // same depth, see if we moved
-        if (gSingleStepControl.step_size == JDWP::SS_MIN) {
+  {
+    // If the debugger is single-stepping one of our threads, check to
+    // see if we're that thread and we've reached a step point.
+    MutexLock mu(Thread::Current(), *Locks::breakpoint_lock_);
+    if (gSingleStepControl.is_active && gSingleStepControl.thread == self) {
+      CHECK(!m->IsNative());
+      if (gSingleStepControl.step_depth == JDWP::SD_INTO) {
+        // Step into method calls.  We break when the line number
+        // or method pointer changes.  If we're in SS_MIN mode, we
+        // always stop.
+        if (gSingleStepControl.method != m) {
+          event_flags |= kSingleStep;
+          VLOG(jdwp) << "SS new method";
+        } else if (gSingleStepControl.step_size == JDWP::SS_MIN) {
           event_flags |= kSingleStep;
           VLOG(jdwp) << "SS new instruction";
         } else if (gSingleStepControl.dex_pcs.find(dex_pc) == gSingleStepControl.dex_pcs.end()) {
           event_flags |= kSingleStep;
           VLOG(jdwp) << "SS new line";
         }
-      }
-    } else {
-      CHECK_EQ(gSingleStepControl.step_depth, JDWP::SD_OUT);
-      // Return from the current method.  We break when the frame
-      // depth pops up.
+      } else if (gSingleStepControl.step_depth == JDWP::SD_OVER) {
+        // Step over method calls.  We break when the line number is
+        // different and the frame depth is <= the original frame
+        // depth.  (We can't just compare on the method, because we
+        // might get unrolled past it by an exception, and it's tricky
+        // to identify recursion.)
 
-      // This differs from the "method exit" break in that it stops
-      // with the PC at the next instruction in the returned-to
-      // function, rather than the end of the returning function.
+        int stack_depth = GetStackDepth(self);
 
-      // TODO: can we just use the value of 'sp'?
-      int stack_depth = GetStackDepth(self);
-      if (stack_depth < gSingleStepControl.stack_depth) {
-        event_flags |= kSingleStep;
-        VLOG(jdwp) << "SS method pop";
+        if (stack_depth < gSingleStepControl.stack_depth) {
+          // popped up one or more frames, always trigger
+          event_flags |= kSingleStep;
+          VLOG(jdwp) << "SS method pop";
+        } else if (stack_depth == gSingleStepControl.stack_depth) {
+          // same depth, see if we moved
+          if (gSingleStepControl.step_size == JDWP::SS_MIN) {
+            event_flags |= kSingleStep;
+            VLOG(jdwp) << "SS new instruction";
+          } else if (gSingleStepControl.dex_pcs.find(dex_pc) == gSingleStepControl.dex_pcs.end()) {
+            event_flags |= kSingleStep;
+            VLOG(jdwp) << "SS new line";
+          }
+        }
+      } else {
+        CHECK_EQ(gSingleStepControl.step_depth, JDWP::SD_OUT);
+        // Return from the current method.  We break when the frame
+        // depth pops up.
+
+        // This differs from the "method exit" break in that it stops
+        // with the PC at the next instruction in the returned-to
+        // function, rather than the end of the returning function.
+
+        int stack_depth = GetStackDepth(self);
+        if (stack_depth < gSingleStepControl.stack_depth) {
+          event_flags |= kSingleStep;
+          VLOG(jdwp) << "SS method pop";
+        }
       }
     }
   }
@@ -2151,14 +2151,14 @@
 }
 
 void Dbg::WatchLocation(const JDWP::JdwpLocation* location) {
-  MutexLock mu(Thread::Current(), gBreakpointsLock);
+  MutexLock mu(Thread::Current(), *Locks::breakpoint_lock_);
   AbstractMethod* m = FromMethodId(location->method_id);
   gBreakpoints.push_back(Breakpoint(m, location->dex_pc));
   VLOG(jdwp) << "Set breakpoint #" << (gBreakpoints.size() - 1) << ": " << gBreakpoints[gBreakpoints.size() - 1];
 }
 
 void Dbg::UnwatchLocation(const JDWP::JdwpLocation* location) {
-  MutexLock mu(Thread::Current(), gBreakpointsLock);
+  MutexLock mu(Thread::Current(), *Locks::breakpoint_lock_);
   AbstractMethod* m = FromMethodId(location->method_id);
   for (size_t i = 0; i < gBreakpoints.size(); ++i) {
     if (gBreakpoints[i].method == m && gBreakpoints[i].dex_pc == location->dex_pc) {
@@ -2178,7 +2178,7 @@
     return JDWP::ERR_INVALID_THREAD;
   }
 
-  MutexLock mu2(soa.Self(), gBreakpointsLock);
+  MutexLock mu2(soa.Self(), *Locks::breakpoint_lock_);
   // TODO: there's no theoretical reason why we couldn't support single-stepping
   // of multiple threads at once, but we never did so historically.
   if (gSingleStepControl.thread != NULL && thread != gSingleStepControl.thread) {
@@ -2194,10 +2194,9 @@
   struct SingleStepStackVisitor : public StackVisitor {
     SingleStepStackVisitor(const ManagedStack* stack,
                            const std::vector<InstrumentationStackFrame>* instrumentation_stack)
-        EXCLUSIVE_LOCKS_REQUIRED(gBreakpointsLock)
+        EXCLUSIVE_LOCKS_REQUIRED(Locks::breakpoint_lock_)
         SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
         : StackVisitor(stack, instrumentation_stack, NULL) {
-      gBreakpointsLock.AssertHeld(Thread::Current());
       gSingleStepControl.method = NULL;
       gSingleStepControl.stack_depth = 0;
     }
@@ -2205,7 +2204,7 @@
     // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses
     // annotalysis.
     bool VisitFrame() NO_THREAD_SAFETY_ANALYSIS {
-      gBreakpointsLock.AssertHeld(Thread::Current());
+      Locks::breakpoint_lock_->AssertHeld(Thread::Current());
       const AbstractMethod* m = GetMethod();
       if (!m->IsRuntimeMethod()) {
         ++gSingleStepControl.stack_depth;
@@ -2230,13 +2229,15 @@
   //
 
   struct DebugCallbackContext {
-    DebugCallbackContext() {
+    DebugCallbackContext() EXCLUSIVE_LOCKS_REQUIRED(Locks::breakpoint_lock_) {
       last_pc_valid = false;
       last_pc = 0;
     }
 
-    static bool Callback(void* raw_context, uint32_t address, uint32_t line_number) {
-      MutexLock mu(Thread::Current(), gBreakpointsLock); // Keep GCC happy.
+    // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses
+    // annotalysis.
+    static bool Callback(void* raw_context, uint32_t address, uint32_t line_number) NO_THREAD_SAFETY_ANALYSIS {
+      Locks::breakpoint_lock_->AssertHeld(Thread::Current());
       DebugCallbackContext* context = reinterpret_cast<DebugCallbackContext*>(raw_context);
       if (static_cast<int32_t>(line_number) == gSingleStepControl.line_number) {
         if (!context->last_pc_valid) {
@@ -2256,8 +2257,10 @@
       return false; // There may be multiple entries for any given line.
     }
 
-    ~DebugCallbackContext() {
-      MutexLock mu(Thread::Current(), gBreakpointsLock); // Keep GCC happy.
+    // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses
+    // annotalysis.
+    ~DebugCallbackContext() NO_THREAD_SAFETY_ANALYSIS {
+      Locks::breakpoint_lock_->AssertHeld(Thread::Current());
       // If the line number was the last in the position table...
       if (last_pc_valid) {
         size_t end = MethodHelper(gSingleStepControl.method).GetCodeItem()->insns_size_in_code_units_;
@@ -2307,7 +2310,7 @@
 }
 
 void Dbg::UnconfigureStep(JDWP::ObjectId /*threadId*/) {
-  MutexLock mu(Thread::Current(), gBreakpointsLock);
+  MutexLock mu(Thread::Current(), *Locks::breakpoint_lock_);
 
   gSingleStepControl.is_active = false;
   gSingleStepControl.thread = NULL;
diff --git a/src/debugger.h b/src/debugger.h
index f9d00d1..d7d2800 100644
--- a/src/debugger.h
+++ b/src/debugger.h
@@ -94,7 +94,7 @@
    * when the debugger attaches.
    */
   static void Connected();
-  static void GoActive();
+  static void GoActive() LOCKS_EXCLUDED(Locks::breakpoint_lock_);
   static void Disconnected();
   static void Disposed();
 
@@ -295,17 +295,20 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   static void UpdateDebugger(int32_t dex_pc, Thread* self)
+      LOCKS_EXCLUDED(Locks::breakpoint_lock_)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   static void WatchLocation(const JDWP::JdwpLocation* pLoc)
+      LOCKS_EXCLUDED(Locks::breakpoint_lock_)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   static void UnwatchLocation(const JDWP::JdwpLocation* pLoc)
+      LOCKS_EXCLUDED(Locks::breakpoint_lock_)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   static JDWP::JdwpError ConfigureStep(JDWP::ObjectId threadId, JDWP::JdwpStepSize size,
                                        JDWP::JdwpStepDepth depth)
-      LOCKS_EXCLUDED(gBreakpointsLock)
+      LOCKS_EXCLUDED(Locks::breakpoint_lock_)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  static void UnconfigureStep(JDWP::ObjectId threadId);
+  static void UnconfigureStep(JDWP::ObjectId threadId) LOCKS_EXCLUDED(Locks::breakpoint_lock_);
 
   static JDWP::JdwpError InvokeMethod(JDWP::ObjectId threadId, JDWP::ObjectId objectId,
                                       JDWP::RefTypeId classId, JDWP::MethodId methodId,
diff --git a/src/locks.cc b/src/locks.cc
index 312b021..0422aff 100644
--- a/src/locks.cc
+++ b/src/locks.cc
@@ -21,6 +21,7 @@
 namespace art {
 
 Mutex* Locks::abort_lock_ = NULL;
+Mutex* Locks::breakpoint_lock_ = NULL;
 Mutex* Locks::classlinker_classes_lock_ = NULL;
 ReaderWriterMutex* Locks::heap_bitmap_lock_ = NULL;
 Mutex* Locks::logging_lock_ = NULL;
@@ -34,6 +35,7 @@
   if (logging_lock_ != NULL) {
     // Already initialized.
     DCHECK(abort_lock_ != NULL);
+    DCHECK(breakpoint_lock_ != NULL);
     DCHECK(classlinker_classes_lock_ != NULL);
     DCHECK(heap_bitmap_lock_ != NULL);
     DCHECK(logging_lock_ != NULL);
@@ -45,6 +47,8 @@
     logging_lock_ = new Mutex("logging lock", kLoggingLock, true);
     abort_lock_ = new Mutex("abort lock", kAbortLock, true);
 
+    DCHECK(breakpoint_lock_ == NULL);
+    breakpoint_lock_ = new Mutex("breakpoint lock", kBreakpointLock);
     DCHECK(classlinker_classes_lock_ == NULL);
     classlinker_classes_lock_ = new Mutex("ClassLinker classes lock", kClassLinkerClassesLock);
     DCHECK(heap_bitmap_lock_ == NULL);
diff --git a/src/locks.h b/src/locks.h
index 9da7711..9a59dca 100644
--- a/src/locks.h
+++ b/src/locks.h
@@ -40,16 +40,17 @@
   kAllocSpaceLock = 5,
   kLoadLibraryLock = 6,
   kClassLinkerClassesLock = 7,
-  kThreadListLock = 8,
-  kJdwpEventListLock = 9,
-  kJdwpAttachLock = 10,
-  kJdwpStartLock = 11,
-  kJdwpSerialLock = 12,
-  kRuntimeShutdownLock = 13,
-  kHeapBitmapLock = 14,
-  kMonitorLock = 15,
-  kMutatorLock = 16,
-  kZygoteCreationLock = 17,
+  kBreakpointLock = 8,
+  kThreadListLock = 9,
+  kJdwpEventListLock = 10,
+  kJdwpAttachLock = 11,
+  kJdwpStartLock = 12,
+  kJdwpSerialLock = 13,
+  kRuntimeShutdownLock = 14,
+  kHeapBitmapLock = 15,
+  kMonitorLock = 16,
+  kMutatorLock = 17,
+  kZygoteCreationLock = 18,
   kMaxMutexLevel = kZygoteCreationLock,
 };
 std::ostream& operator<<(std::ostream& os, const LockLevel& rhs);
@@ -129,8 +130,11 @@
   // attaching and detaching.
   static Mutex* thread_list_lock_ ACQUIRED_AFTER(runtime_shutdown_lock_);
 
+  // Guards breakpoints and single-stepping.
+  static Mutex* breakpoint_lock_ ACQUIRED_AFTER(thread_list_lock_);
+
   // Guards lists of classes within the class linker.
-  static Mutex* classlinker_classes_lock_ ACQUIRED_AFTER(thread_list_lock_);
+  static Mutex* classlinker_classes_lock_ ACQUIRED_AFTER(breakpoint_lock_);
 
   // When declaring any Mutex add DEFAULT_MUTEX_ACQUIRED_AFTER to use annotalysis to check the code
   // doesn't try to hold a higher level Mutex.