Extend and fix the monitor diagnostics.

1. Including kSleeping as one of the interesting states.

2. Reset the wait_monitor_ field later so that a thread caught trying to switch
back to kRunnable doesn't show up as waiting/sleeping on "null". This only
came to light because my wait/sleep additions to the ThreadStress test all do
very short waits/sleeps.

3. Remove the bogus "held by" output. You can only wait/sleep on a monitor you
hold, so we know the answer already (and this code was producing the wrong
answer because it was using stale data).

Change-Id: I23135862c2a429f4eee222756d3ff35204d12d62
diff --git a/src/monitor.cc b/src/monitor.cc
index 7cdccac..b98aa04 100644
--- a/src/monitor.cc
+++ b/src/monitor.cc
@@ -430,7 +430,7 @@
    */
   self->TransitionFromRunnableToSuspended(why);
 
-  bool wasInterrupted = false;
+  bool was_interrupted = false;
   {
     // Pseudo-atomically wait on self's wait_cond_ and release the monitor lock.
     MutexLock mu(self, *self->wait_mutex_);
@@ -444,12 +444,9 @@
     // Release the monitor lock.
     Unlock(self, true);
 
-    /*
-     * Handle the case where the thread was interrupted before we called
-     * wait().
-     */
+    // Handle the case where the thread was interrupted before we called wait().
     if (self->interrupted_) {
-      wasInterrupted = true;
+      was_interrupted = true;
     } else {
       // Wait for a notification or a timeout to occur.
       if (why == kWaiting) {
@@ -459,20 +456,28 @@
         self->wait_cond_->TimedWait(self, ms, ns);
       }
       if (self->interrupted_) {
-        wasInterrupted = true;
+        was_interrupted = true;
       }
       self->interrupted_ = false;
     }
-    self->wait_monitor_ = NULL;
   }
 
   // Set self->status back to kRunnable, and self-suspend if needed.
   self->TransitionFromSuspendedToRunnable();
 
+  {
+    // We reset the thread's wait_monitor_ field after transitioning back to runnable so
+    // that a thread in a waiting/sleeping state has a non-null wait_monitor_ for debugging
+    // and diagnostic purposes. (If you reset this earlier, stack dumps will claim that threads
+    // are waiting on "null".)
+    MutexLock mu(self, *self->wait_mutex_);
+    DCHECK(self->wait_monitor_ != NULL);
+    self->wait_monitor_ = NULL;
+  }
+
   // Re-acquire the monitor lock.
   Lock(self);
 
-
   self->wait_mutex_->AssertNotHeld(self);
 
   /*
@@ -487,7 +492,7 @@
   locking_dex_pc_ = saved_dex_pc;
   RemoveFromWaitSet(self);
 
-  if (wasInterrupted) {
+  if (was_interrupted) {
     /*
      * We were interrupted while waiting, or somebody interrupted an
      * un-interruptible thread earlier and we're bailing out immediately.
@@ -809,43 +814,25 @@
   }
 }
 
-static uint32_t LockOwnerFromThreadLock(Object* thread_lock) {
-  ScopedObjectAccess soa(Thread::Current());
-  if (thread_lock == NULL ||
-      thread_lock->GetClass() != soa.Decode<Class*>(WellKnownClasses::java_lang_ThreadLock)) {
-    return ThreadList::kInvalidId;
-  }
-  Field* thread_field = soa.DecodeField(WellKnownClasses::java_lang_ThreadLock_thread);
-  Object* managed_thread = thread_field->GetObject(thread_lock);
-  if (managed_thread == NULL) {
-    return ThreadList::kInvalidId;
-  }
-  Field* vmData_field = soa.DecodeField(WellKnownClasses::java_lang_Thread_vmData);
-  uintptr_t vmData = static_cast<uintptr_t>(vmData_field->GetInt(managed_thread));
-  Thread* thread = reinterpret_cast<Thread*>(vmData);
-  if (thread == NULL) {
-    return ThreadList::kInvalidId;
-  }
-  return thread->GetThinLockId();
-}
-
 void Monitor::DescribeWait(std::ostream& os, const Thread* thread) {
   ThreadState state;
   state = thread->GetState();
 
   Object* object = NULL;
   uint32_t lock_owner = ThreadList::kInvalidId;
-  if (state == kWaiting || state == kTimedWaiting) {
-    os << "  - waiting on ";
-    Monitor* monitor;
+  if (state == kWaiting || state == kTimedWaiting || state == kSleeping) {
+    if (state == kSleeping) {
+      os << "  - sleeping on ";
+    } else {
+      os << "  - waiting on ";
+    }
     {
       MutexLock mu(Thread::Current(), *thread->wait_mutex_);
-      monitor = thread->wait_monitor_;
+      Monitor* monitor = thread->wait_monitor_;
+      if (monitor != NULL) {
+        object = monitor->obj_;
+      }
     }
-    if (monitor != NULL) {
-      object = monitor->obj_;
-    }
-    lock_owner = LockOwnerFromThreadLock(object);
   } else if (state == kBlocked) {
     os << "  - waiting to lock ";
     object = thread->monitor_enter_object_;
@@ -857,10 +844,10 @@
     return;
   }
 
-  // - waiting on <0x613f83d8> (a java.lang.ThreadLock) held by thread 5
   // - waiting on <0x6008c468> (a java.lang.Class<java.lang.ref.ReferenceQueue>)
   os << "<" << object << "> (a " << PrettyTypeOf(object) << ")";
 
+  // - waiting to lock <0x613f83d8> (a java.lang.ThreadLock) held by thread 5
   if (lock_owner != ThreadList::kInvalidId) {
     os << " held by thread " << lock_owner;
   }
diff --git a/src/well_known_classes.cc b/src/well_known_classes.cc
index 2c16be9..6a0e709 100644
--- a/src/well_known_classes.cc
+++ b/src/well_known_classes.cc
@@ -38,7 +38,6 @@
 jclass WellKnownClasses::java_lang_Thread;
 jclass WellKnownClasses::java_lang_Thread$UncaughtExceptionHandler;
 jclass WellKnownClasses::java_lang_ThreadGroup;
-jclass WellKnownClasses::java_lang_ThreadLock;
 jclass WellKnownClasses::java_lang_Throwable;
 jclass WellKnownClasses::java_nio_ReadWriteDirectByteBuffer;
 jclass WellKnownClasses::org_apache_harmony_dalvik_ddmc_Chunk;
@@ -80,7 +79,6 @@
 jfieldID WellKnownClasses::java_lang_ThreadGroup_mainThreadGroup;
 jfieldID WellKnownClasses::java_lang_ThreadGroup_name;
 jfieldID WellKnownClasses::java_lang_ThreadGroup_systemThreadGroup;
-jfieldID WellKnownClasses::java_lang_ThreadLock_thread;
 jfieldID WellKnownClasses::java_lang_reflect_Proxy_h;
 jfieldID WellKnownClasses::java_nio_ReadWriteDirectByteBuffer_capacity;
 jfieldID WellKnownClasses::java_nio_ReadWriteDirectByteBuffer_effectiveDirectAddress;
@@ -134,7 +132,6 @@
   java_lang_Thread = CacheClass(env, "java/lang/Thread");
   java_lang_Thread$UncaughtExceptionHandler = CacheClass(env, "java/lang/Thread$UncaughtExceptionHandler");
   java_lang_ThreadGroup = CacheClass(env, "java/lang/ThreadGroup");
-  java_lang_ThreadLock = CacheClass(env, "java/lang/ThreadLock");
   java_lang_Throwable = CacheClass(env, "java/lang/Throwable");
   java_nio_ReadWriteDirectByteBuffer = CacheClass(env, "java/nio/ReadWriteDirectByteBuffer");
   org_apache_harmony_dalvik_ddmc_Chunk = CacheClass(env, "org/apache/harmony/dalvik/ddmc/Chunk");
@@ -176,7 +173,6 @@
   java_lang_ThreadGroup_mainThreadGroup = CacheField(env, java_lang_ThreadGroup, true, "mainThreadGroup", "Ljava/lang/ThreadGroup;");
   java_lang_ThreadGroup_name = CacheField(env, java_lang_ThreadGroup, false, "name", "Ljava/lang/String;");
   java_lang_ThreadGroup_systemThreadGroup = CacheField(env, java_lang_ThreadGroup, true, "systemThreadGroup", "Ljava/lang/ThreadGroup;");
-  java_lang_ThreadLock_thread = CacheField(env, java_lang_ThreadLock, false, "thread", "Ljava/lang/Thread;");
   java_lang_reflect_Proxy_h = CacheField(env, java_lang_reflect_Proxy, false, "h", "Ljava/lang/reflect/InvocationHandler;");
   java_nio_ReadWriteDirectByteBuffer_capacity = CacheField(env, java_nio_ReadWriteDirectByteBuffer, false, "capacity", "I");
   java_nio_ReadWriteDirectByteBuffer_effectiveDirectAddress = CacheField(env, java_nio_ReadWriteDirectByteBuffer, false, "effectiveDirectAddress", "I");
diff --git a/src/well_known_classes.h b/src/well_known_classes.h
index f2c479c..3dbf8a1 100644
--- a/src/well_known_classes.h
+++ b/src/well_known_classes.h
@@ -49,7 +49,6 @@
   static jclass java_lang_StackOverflowError;
   static jclass java_lang_Thread;
   static jclass java_lang_ThreadGroup;
-  static jclass java_lang_ThreadLock;
   static jclass java_lang_Thread$UncaughtExceptionHandler;
   static jclass java_lang_Throwable;
   static jclass java_nio_ReadWriteDirectByteBuffer;
@@ -93,7 +92,6 @@
   static jfieldID java_lang_ThreadGroup_mainThreadGroup;
   static jfieldID java_lang_ThreadGroup_name;
   static jfieldID java_lang_ThreadGroup_systemThreadGroup;
-  static jfieldID java_lang_ThreadLock_thread;
   static jfieldID java_nio_ReadWriteDirectByteBuffer_capacity;
   static jfieldID java_nio_ReadWriteDirectByteBuffer_effectiveDirectAddress;
   static jfieldID org_apache_harmony_dalvik_ddmc_Chunk_data;