Include held locks in SIGQUIT thread dumps.

Handy if you have an ANR that's locking related. Quick tour:

   at org.apache.harmony.dalvik.NativeTestTarget.emptyJniStaticSynchronizedMethod0(Native method)
   - locked <0x60135aa8> (a java.lang.Class<org.apache.harmony.dalvik.NativeTestTarget>)
   at java.lang.reflect.Method.invoke(Native method)
   at C.whileTrue(Main.java:63)
   at C.synchronizedOnClassString(Main.java:56)
   - locked <0x60002a70> (a java.lang.Class<java.lang.String>)
   at C.nestedSynchronizationWithTryCatch(Main.java:44)
   - locked <0x61336b90> (a java.lang.String)
   - locked <0x61336bd0> (a java.lang.String)
   at C.nestedSynchronization(Main.java:35)
   - locked <0x61336b18> (a java.lang.String)
   - locked <0x61336b50> (a java.lang.String)
   at C.synchronizedOnClassC(Main.java:30)
   - locked <0x613366f8> (a java.lang.Class<C>)
   at C.noLocks(Main.java:27)
   at C.<clinit>(Main.java:24)
   - locked <0x613366f8> (a java.lang.Class<C>)
   at Main.main(Main.java:19)

A non-static synchronized native method works too:

   at org.apache.harmony.dalvik.NativeTestTarget.emptyJniSynchronizedMethod0(Native method)
   - locked <0x613371a8> (a org.apache.harmony.dalvik.NativeTestTarget)
   ...

Note that most stack traces don't look any different; the above is a
pathological example that exercises different kinds of locking. Testing
with system_server shows most threads don't hold any locks.

Future work (marked by TODO) is that explicit JNI MonitorEnter calls in
native code aren't shown.

Change-Id: I2747f5cddb4ef64b1935736f084a68fe8e4005e9
diff --git a/src/thread.cc b/src/thread.cc
index 9f88f5a..8fe0160 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -519,9 +519,10 @@
 }
 
 struct StackDumpVisitor : public StackVisitor {
-  StackDumpVisitor(std::ostream& os, const Thread* thread)
-      : StackVisitor(thread->GetManagedStack(), thread->GetTraceStack()), last_method(NULL),
-        last_line_number(0), repetition_count(0), os(os), thread(thread), frame_count(0) {
+  StackDumpVisitor(std::ostream& os, const Thread* thread, Context* context, bool can_allocate)
+      : StackVisitor(thread->GetManagedStack(), thread->GetTraceStack(), context),
+        os(os), thread(thread), can_allocate(can_allocate),
+        last_method(NULL), last_line_number(0), repetition_count(0), frame_count(0) {
   }
 
   virtual ~StackDumpVisitor() {
@@ -565,19 +566,24 @@
            << ":" << line_number << ")";
       }
       os << "\n";
+      if (frame_count == 0) {
+        Monitor::DescribeWait(os, thread);
+      }
+      if (can_allocate) {
+        Monitor::DescribeLocks(os, this);
+      }
     }
 
-    if (frame_count++ == 0) {
-      Monitor::DescribeWait(os, thread);
-    }
+    ++frame_count;
     return true;
   }
+  std::ostream& os;
+  const Thread* thread;
+  bool can_allocate;
   MethodHelper mh;
   Method* last_method;
   int last_line_number;
   int repetition_count;
-  std::ostream& os;
-  const Thread* thread;
   int frame_count;
 };
 
@@ -587,7 +593,8 @@
     DumpKernelStack(os, GetTid(), "  kernel: ", false);
     DumpNativeStack(os, GetTid(), "  native: ", false);
   }
-  StackDumpVisitor dumper(os, this);
+  UniquePtr<Context> context(Context::Create());
+  StackDumpVisitor dumper(os, this, context.get(), !throwing_OutOfMemoryError_);
   dumper.WalkStack();
 }
 
@@ -999,7 +1006,8 @@
  public:
   CountStackDepthVisitor(const ManagedStack* stack,
                          const std::vector<TraceStackFrame>* trace_stack)
-      : StackVisitor(stack, trace_stack), depth_(0), skip_depth_(0), skipping_(true) {}
+      : StackVisitor(stack, trace_stack, NULL),
+        depth_(0), skip_depth_(0), skipping_(true) {}
 
   bool VisitFrame() {
     // We want to skip frames up to and including the exception's constructor.
@@ -1039,8 +1047,8 @@
   explicit BuildInternalStackTraceVisitor(const ManagedStack* stack,
                                           const std::vector<TraceStackFrame>* trace_stack,
                                           int skip_depth)
-      : StackVisitor(stack, trace_stack), skip_depth_(skip_depth), count_(0), dex_pc_trace_(NULL),
-        method_trace_(NULL) {}
+      : StackVisitor(stack, trace_stack, NULL),
+        skip_depth_(skip_depth), count_(0), dex_pc_trace_(NULL), method_trace_(NULL) {}
 
   bool Init(int depth, const ScopedJniThreadState& ts) {
     // Allocate method trace with an extra slot that will hold the PC trace
@@ -1551,7 +1559,7 @@
   struct CurrentMethodVisitor : public StackVisitor {
     CurrentMethodVisitor(const ManagedStack* stack,
                          const std::vector<TraceStackFrame>* trace_stack)
-        : StackVisitor(stack, trace_stack), method_(NULL), dex_pc_(0), frame_id_(0) {}
+        : StackVisitor(stack, trace_stack, NULL), method_(NULL), dex_pc_(0), frame_id_(0) {}
 
     virtual bool VisitFrame() {
       Method* m = GetMethod();