libcorkscrew native stacks, mutex ranking, and better ScopedThreadListLock.

This change uses libcorkscrew to show native stacks for threads in kNative or,
unlike dalvikvm, kVmWait --- working on the runtime directly I've found it
somewhat useful to be able to see _which_ internal resource we're waiting on.
We can always take that back out (or make it oatexecd-only) if it turns out to
be too noisy/confusing for app developers.

This change also lets us rank mutexes and enforce -- in oatexecd -- that you
take locks in a specific order.

Both of these helped me test the third novelty: removing the heap locking from
ScopedThreadListLock. I've manually inspected all the callers and added a
ScopedHeapLock where I think one is necessary. In manual testing, this makes
jdb a lot less prone to locking us up. There still seems to be a problem with
the JDWP VirtualMachine.Resume command, but I'll look at that separately. This
is a big enough and potentially disruptive enough change already.

Change-Id: Iad974358919d0e00674662dc8a69cc65878cfb5c
diff --git a/src/monitor.cc b/src/monitor.cc
index e3c98bb..7261bc4 100644
--- a/src/monitor.cc
+++ b/src/monitor.cc
@@ -249,49 +249,60 @@
   return oss.str();
 }
 
-void Monitor::FailedUnlock(Object* obj, Thread* expected_owner, Thread* found_owner,
-                           Monitor* mon) {
-  // Acquire thread list lock so threads won't disappear from under us
-  ScopedThreadListLock thread_list_lock;
-  // Re-read owner now that we hold lock
-  Thread* current_owner = mon != NULL ? mon->owner_ : NULL;
+void Monitor::FailedUnlock(Object* o, Thread* expected_owner, Thread* found_owner,
+                           Monitor* monitor) {
+  Thread* current_owner = NULL;
+  std::string current_owner_string;
+  std::string expected_owner_string;
+  std::string found_owner_string;
+  {
+    // TODO: isn't this too late to prevent threads from disappearing?
+    // Acquire thread list lock so threads won't disappear from under us.
+    ScopedThreadListLock thread_list_lock;
+    // Re-read owner now that we hold lock.
+    current_owner = (monitor != NULL) ? monitor->owner_ : NULL;
+    // Get short descriptions of the threads involved.
+    current_owner_string = ThreadToString(current_owner);
+    expected_owner_string = ThreadToString(expected_owner);
+    found_owner_string = ThreadToString(found_owner);
+  }
   if (current_owner == NULL) {
     if (found_owner == NULL) {
       ThrowIllegalMonitorStateExceptionF("unlock of unowned monitor on object of type '%s'"
                                          " on thread '%s'",
-                                         PrettyTypeOf(obj).c_str(),
-                                         ThreadToString(expected_owner).c_str());
+                                         PrettyTypeOf(o).c_str(),
+                                         expected_owner_string.c_str());
     } else {
       // Race: the original read found an owner but now there is none
       ThrowIllegalMonitorStateExceptionF("unlock of monitor owned by '%s' on object of type '%s'"
                                          " (where now the monitor appears unowned) on thread '%s'",
-                                         ThreadToString(found_owner).c_str(),
-                                         PrettyTypeOf(obj).c_str(),
-                                         ThreadToString(expected_owner).c_str());
+                                         found_owner_string.c_str(),
+                                         PrettyTypeOf(o).c_str(),
+                                         expected_owner_string.c_str());
     }
   } else {
     if (found_owner == NULL) {
       // Race: originally there was no owner, there is now
       ThrowIllegalMonitorStateExceptionF("unlock of monitor owned by '%s' on object of type '%s'"
                                          " (originally believed to be unowned) on thread '%s'",
-                                         ThreadToString(current_owner).c_str(),
-                                         PrettyTypeOf(obj).c_str(),
-                                         ThreadToString(expected_owner).c_str());
+                                         current_owner_string.c_str(),
+                                         PrettyTypeOf(o).c_str(),
+                                         expected_owner_string.c_str());
     } else {
       if (found_owner != current_owner) {
         // Race: originally found and current owner have changed
         ThrowIllegalMonitorStateExceptionF("unlock of monitor originally owned by '%s' (now"
                                            " owned by '%s') on object of type '%s' on thread '%s'",
-                                           ThreadToString(found_owner).c_str(),
-                                           ThreadToString(current_owner).c_str(),
-                                           PrettyTypeOf(obj).c_str(),
-                                           ThreadToString(expected_owner).c_str());
+                                           found_owner_string.c_str(),
+                                           current_owner_string.c_str(),
+                                           PrettyTypeOf(o).c_str(),
+                                           expected_owner_string.c_str());
       } else {
         ThrowIllegalMonitorStateExceptionF("unlock of monitor owned by '%s' on object of type '%s'"
                                            " on thread '%s",
-                                           ThreadToString(current_owner).c_str(),
-                                           PrettyTypeOf(obj).c_str(),
-                                           ThreadToString(expected_owner).c_str());
+                                           current_owner_string.c_str(),
+                                           PrettyTypeOf(o).c_str(),
+                                           expected_owner_string.c_str());
       }
     }
   }