Implement the Thread.sleep native method.

This makes returning TS_SLEEPING from JDWP simple and cheap, and
makes the stack dumps for sleeping threads more easily understood
by app developers (because there's no Object.wait magic going, and
the thread state is "Sleeping" rather than "TimedWaiting").

Also make Object.wait() a native method in its own right, so every call into
Monitor::Wait can explicitly pass the most appropriate ThreadState: kSleeping,
kWaiting, or kTimedWaiting.

Also add Thread.sleep and Object.wait(long, int) calls to the ThreadStress test.

Change-Id: I49adb45dbcd669eba7cf3def45e6cbfc461a3254
diff --git a/src/debugger.cc b/src/debugger.cc
index 158be0b..5240c6c 100644
--- a/src/debugger.cc
+++ b/src/debugger.cc
@@ -1424,6 +1424,7 @@
     case kTerminated:   *pThreadStatus = JDWP::TS_ZOMBIE;   break;
     case kRunnable:     *pThreadStatus = JDWP::TS_RUNNING;  break;
     case kTimedWaiting: *pThreadStatus = JDWP::TS_WAIT;     break;
+    case kSleeping:     *pThreadStatus = JDWP::TS_SLEEPING; break;
     case kBlocked:      *pThreadStatus = JDWP::TS_MONITOR;  break;
     case kWaiting:      *pThreadStatus = JDWP::TS_WAIT;     break;
     case kStarting:     *pThreadStatus = JDWP::TS_ZOMBIE;   break;
@@ -1442,34 +1443,6 @@
     // Don't add a 'default' here so the compiler can spot incompatible enum changes.
   }
 
-  if (thread->GetState() == kTimedWaiting) {
-    // Since Thread.sleep is implemented using Object.wait, see if Thread.sleep
-    // is on the stack and change state to TS_SLEEPING if it is.
-    struct SleepMethodVisitor : public StackVisitor {
-      SleepMethodVisitor(const ManagedStack* stack,
-                         const std::deque<InstrumentationStackFrame>* instrumentation_stack)
-          SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-          : StackVisitor(stack, instrumentation_stack, NULL), found_(false) {}
-
-      virtual bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-        std::string name(PrettyMethod(GetMethod(), false));
-        if (name == "java.lang.Thread.sleep") {
-          found_ = true;
-          return false;
-        }
-        return true;
-      }
-
-      bool found_;
-    };
-
-    SleepMethodVisitor visitor(thread->GetManagedStack(), thread->GetInstrumentationStack());
-    visitor.WalkStack(false);
-    if (visitor.found_) {
-      *pThreadStatus = JDWP::TS_SLEEPING;
-    }
-  }
-
   *pSuspendStatus = (thread->IsSuspended() ? JDWP::SUSPEND_STATUS_SUSPENDED : JDWP::SUSPEND_STATUS_NOT_SUSPENDED);
 
   return true;
diff --git a/src/monitor.cc b/src/monitor.cc
index 33383eb..7cdccac 100644
--- a/src/monitor.cc
+++ b/src/monitor.cc
@@ -379,8 +379,11 @@
  * Since we're allowed to wake up "early", we clamp extremely long durations
  * to return at the end of the 32-bit time epoch.
  */
-void Monitor::Wait(Thread* self, int64_t ms, int32_t ns, bool interruptShouldThrow) {
+void Monitor::Wait(Thread* self, int64_t ms, int32_t ns,
+                   bool interruptShouldThrow, ThreadState why) {
   DCHECK(self != NULL);
+  DCHECK(why == kTimedWaiting || why == kWaiting || why == kSleeping);
+  DCHECK(why != kWaiting || (ms == 0 && ns == 0));
 
   // Make sure that we hold the lock.
   if (owner_ != self) {
@@ -388,10 +391,12 @@
     return;
   }
   monitor_lock_.AssertHeld(self);
-  WaitWithLock(self, ms, ns, interruptShouldThrow);
+
+  WaitWithLock(self, ms, ns, interruptShouldThrow, why);
 }
 
-void Monitor::WaitWithLock(Thread* self, int64_t ms, int32_t ns, bool interruptShouldThrow) {
+void Monitor::WaitWithLock(Thread* self, int64_t ms, int32_t ns,
+                           bool interruptShouldThrow, ThreadState why) {
   // Enforce the timeout range.
   if (ms < 0 || ns < 0 || ns > 999999) {
     Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalArgumentException;",
@@ -419,12 +424,11 @@
   locking_dex_pc_ = 0;
 
   /*
-   * Update thread status.  If the GC wakes up, it'll ignore us, knowing
+   * Update thread state. If the GC wakes up, it'll ignore us, knowing
    * that we won't touch any references in this state, and we'll check
    * our suspend mode before we transition out.
    */
-  bool timed = (ms != 0 || ns != 0);
-  self->TransitionFromRunnableToSuspended(timed ? kTimedWaiting : kWaiting);
+  self->TransitionFromRunnableToSuspended(why);
 
   bool wasInterrupted = false;
   {
@@ -448,9 +452,10 @@
       wasInterrupted = true;
     } else {
       // Wait for a notification or a timeout to occur.
-      if (!timed) {
+      if (why == kWaiting) {
         self->wait_cond_->Wait(self);
       } else {
+        DCHECK(why == kTimedWaiting || why == kSleeping) << why;
         self->wait_cond_->TimedWait(self, ms, ns);
       }
       if (self->interrupted_) {
@@ -733,7 +738,8 @@
 /*
  * Object.wait().  Also called for class init.
  */
-void Monitor::Wait(Thread* self, Object *obj, int64_t ms, int32_t ns, bool interruptShouldThrow) {
+void Monitor::Wait(Thread* self, Object *obj, int64_t ms, int32_t ns,
+                   bool interruptShouldThrow, ThreadState why) {
   volatile int32_t* thinp = obj->GetRawLockWordAddress();
 
   // If the lock is still thin, we need to fatten it.
@@ -753,7 +759,7 @@
     Inflate(self, obj);
     VLOG(monitor) << StringPrintf("monitor: thread %d fattened lock %p by wait()", self->GetThinLockId(), thinp);
   }
-  LW_MONITOR(*thinp)->Wait(self, ms, ns, interruptShouldThrow);
+  LW_MONITOR(*thinp)->Wait(self, ms, ns, interruptShouldThrow, why);
 }
 
 void Monitor::Notify(Thread* self, Object *obj) {
diff --git a/src/monitor.h b/src/monitor.h
index c3b4b21..977a7f1 100644
--- a/src/monitor.h
+++ b/src/monitor.h
@@ -82,7 +82,7 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   static void NotifyAll(Thread* self, Object* obj)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  static void Wait(Thread* self, Object* obj, int64_t ms, int32_t ns, bool interruptShouldThrow)
+  static void Wait(Thread* self, Object* obj, int64_t ms, int32_t ns, bool interruptShouldThrow, ThreadState why)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   static void DescribeWait(std::ostream& os, const Thread* thread)
@@ -125,9 +125,9 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
 
-  void Wait(Thread* self, int64_t msec, int32_t nsec, bool interruptShouldThrow)
+  void Wait(Thread* self, int64_t msec, int32_t nsec, bool interruptShouldThrow, ThreadState why)
       NO_THREAD_SAFETY_ANALYSIS;
-  void WaitWithLock(Thread* self, int64_t ms, int32_t ns, bool interruptShouldThrow)
+  void WaitWithLock(Thread* self, int64_t ms, int32_t ns, bool interruptShouldThrow, ThreadState why)
       EXCLUSIVE_LOCKS_REQUIRED(monitor_lock_)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
diff --git a/src/native/java_lang_Object.cc b/src/native/java_lang_Object.cc
index bcea373..f3c295e 100644
--- a/src/native/java_lang_Object.cc
+++ b/src/native/java_lang_Object.cc
@@ -18,37 +18,49 @@
 #include "object.h"
 #include "scoped_thread_state_change.h"
 
+// TODO: better support for overloading.
+#undef NATIVE_METHOD
+#define NATIVE_METHOD(className, functionName, signature, identifier) \
+    { #functionName, signature, reinterpret_cast<void*>(className ## _ ## identifier) }
+
 namespace art {
 
-static jobject Object_internalClone(JNIEnv* env, jobject javaThis) {
+static jobject Object_internalClone(JNIEnv* env, jobject java_this) {
   ScopedObjectAccess soa(env);
-  Object* o = soa.Decode<Object*>(javaThis);
+  Object* o = soa.Decode<Object*>(java_this);
   return soa.AddLocalReference<jobject>(o->Clone(soa.Self()));
 }
 
-static void Object_notify(JNIEnv* env, jobject javaThis) {
+static void Object_notify(JNIEnv* env, jobject java_this) {
   ScopedObjectAccess soa(env);
-  Object* o = soa.Decode<Object*>(javaThis);
+  Object* o = soa.Decode<Object*>(java_this);
   o->Notify();
 }
 
-static void Object_notifyAll(JNIEnv* env, jobject javaThis) {
+static void Object_notifyAll(JNIEnv* env, jobject java_this) {
   ScopedObjectAccess soa(env);
-  Object* o = soa.Decode<Object*>(javaThis);
+  Object* o = soa.Decode<Object*>(java_this);
   o->NotifyAll();
 }
 
-static void Object_wait(JNIEnv* env, jobject javaThis, jlong ms, jint ns) {
+static void Object_wait(JNIEnv* env, jobject java_this) {
   ScopedObjectAccess soa(env);
-  Object* o = soa.Decode<Object*>(javaThis);
+  Object* o = soa.Decode<Object*>(java_this);
+  o->Wait();
+}
+
+static void Object_waitJI(JNIEnv* env, jobject java_this, jlong ms, jint ns) {
+  ScopedObjectAccess soa(env);
+  Object* o = soa.Decode<Object*>(java_this);
   o->Wait(ms, ns);
 }
 
 static JNINativeMethod gMethods[] = {
-  NATIVE_METHOD(Object, internalClone, "()Ljava/lang/Object;"),
-  NATIVE_METHOD(Object, notify, "()V"),
-  NATIVE_METHOD(Object, notifyAll, "()V"),
-  NATIVE_METHOD(Object, wait, "(JI)V"),
+  NATIVE_METHOD(Object, internalClone, "()Ljava/lang/Object;", internalClone),
+  NATIVE_METHOD(Object, notify, "()V", notify),
+  NATIVE_METHOD(Object, notifyAll, "()V", notifyAll),
+  NATIVE_METHOD(Object, wait, "()V", wait),
+  NATIVE_METHOD(Object, wait, "(JI)V", waitJI),
 };
 
 void register_java_lang_Object(JNIEnv* env) {
diff --git a/src/native/java_lang_Thread.cc b/src/native/java_lang_Thread.cc
index f14c03b..8db217e 100644
--- a/src/native/java_lang_Thread.cc
+++ b/src/native/java_lang_Thread.cc
@@ -16,6 +16,7 @@
 
 #include "debugger.h"
 #include "jni_internal.h"
+#include "monitor.h"
 #include "object.h"
 #include "scoped_thread_state_change.h"
 #include "ScopedUtfChars.h"
@@ -65,6 +66,7 @@
     case kTerminated:                     return kJavaTerminated;
     case kRunnable:                       return kJavaRunnable;
     case kTimedWaiting:                   return kJavaTimedWaiting;
+    case kSleeping:                       return kJavaTimedWaiting;
     case kBlocked:                        return kJavaBlocked;
     case kWaiting:                        return kJavaWaiting;
     case kStarting:                       return kJavaNew;
@@ -145,6 +147,12 @@
   }
 }
 
+static void Thread_sleep(JNIEnv* env, jclass, jobject java_lock, jlong ms, jint ns) {
+  ScopedObjectAccess soa(env);
+  Object* lock = soa.Decode<Object*>(java_lock);
+  Monitor::Wait(Thread::Current(), lock, ms, ns, true, kSleeping);
+}
+
 /*
  * Causes the thread to temporarily pause and allow other threads to execute.
  *
@@ -165,6 +173,7 @@
   NATIVE_METHOD(Thread, nativeInterrupt, "()V"),
   NATIVE_METHOD(Thread, nativeSetName, "(Ljava/lang/String;)V"),
   NATIVE_METHOD(Thread, nativeSetPriority, "(I)V"),
+  NATIVE_METHOD(Thread, sleep, "(Ljava/lang/Object;JI)V"),
   NATIVE_METHOD(Thread, yield, "()V"),
 };
 
diff --git a/src/object.cc b/src/object.cc
index c3c4e13..10bf672 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -156,8 +156,12 @@
   Monitor::NotifyAll(Thread::Current(), this);
 }
 
+void Object::Wait() {
+  Monitor::Wait(Thread::Current(), this, 0, 0, true, kWaiting);
+}
+
 void Object::Wait(int64_t ms, int32_t ns) {
-  Monitor::Wait(Thread::Current(), this, ms, ns, true);
+  Monitor::Wait(Thread::Current(), this, ms, ns, true, kTimedWaiting);
 }
 
 #if VERIFY_OBJECT_ENABLED
diff --git a/src/object.h b/src/object.h
index 60e45c3..07bcde1 100644
--- a/src/object.h
+++ b/src/object.h
@@ -164,10 +164,11 @@
 
   void NotifyAll() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  void Wait() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
   void Wait(int64_t timeout) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  void Wait(int64_t timeout, int32_t nanos)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void Wait(int64_t timeout, int32_t nanos) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   bool IsClass() const;
 
diff --git a/src/object_utils.h b/src/object_utils.h
index 6924f4e..dd5ff05 100644
--- a/src/object_utils.h
+++ b/src/object_utils.h
@@ -44,7 +44,7 @@
   }
 
   void Wait() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return Monitor::Wait(self_, obj_, 0, 0, false);
+    return Monitor::Wait(self_, obj_, 0, 0, false, kWaiting);
   }
 
   void Notify() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
diff --git a/src/thread.h b/src/thread.h
index ea49960..7bfc2e8 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -77,23 +77,25 @@
 };
 
 enum ThreadState {
-  kTerminated                     = 0,   // Thread.TERMINATED     JDWP TS_ZOMBIE
-  kRunnable                       = 1,   // Thread.RUNNABLE       JDWP TS_RUNNING
-  kTimedWaiting                   = 2,   // Thread.TIMED_WAITING  JDWP TS_WAIT    - in Object.wait() with a timeout
-  kBlocked                        = 3,   // Thread.BLOCKED        JDWP TS_MONITOR - blocked on a monitor
-  kWaiting                        = 4,   // Thread.WAITING        JDWP TS_WAIT    - in Object.wait()
-  kWaitingForGcToComplete         = 5,   // Thread.WAITING        JDWP TS_WAIT    - blocked waiting for GC
-  kWaitingPerformingGc            = 6,   // Thread.WAITING        JDWP TS_WAIT    - performing GC
-  kWaitingForDebuggerSend         = 7,   // Thread.WAITING        JDWP TS_WAIT    - blocked waiting for events to be sent
-  kWaitingForDebuggerToAttach     = 8,   // Thread.WAITING        JDWP TS_WAIT    - blocked waiting for debugger to attach
-  kWaitingInMainDebuggerLoop      = 9,   // Thread.WAITING        JDWP TS_WAIT    - blocking/reading/processing debugger events
-  kWaitingForDebuggerSuspension   = 10,  // Thread.WAITING        JDWP TS_WAIT    - waiting for debugger suspend all
-  kWaitingForJniOnLoad            = 11,  // Thread.WAITING        JDWP TS_WAIT    - waiting for execution of dlopen and JNI on load code
-  kWaitingForSignalCatcherOutput  = 12,  // Thread.WAITING        JDWP TS_WAIT    - waiting for signal catcher IO to complete
-  kWaitingInMainSignalCatcherLoop = 13,  // Thread.WAITING        JDWP TS_WAIT    - blocking/reading/processing signals
-  kStarting                       = 14,  // Thread.NEW            JDWP TS_WAIT    - native thread started, not yet ready to run managed code
-  kNative                         = 15,  // Thread.RUNNABLE       JDWP TS_RUNNING - running in a JNI native method
-  kSuspended                      = 16,  // Thread.RUNNABLE       JDWP TS_RUNNING - suspended by GC or debugger
+  //                                  Thread.State   JDWP state
+  kTerminated,                     // TERMINATED     TS_ZOMBIE    Thread.run has returned, but Thread* still around
+  kRunnable,                       // RUNNABLE       TS_RUNNING   runnable
+  kTimedWaiting,                   // TIMED_WAITING  TS_WAIT      in Object.wait() with a timeout
+  kSleeping,                       // TIMED_WAITING  TS_SLEEPING  in Thread.sleep()
+  kBlocked,                        // BLOCKED        TS_MONITOR   blocked on a monitor
+  kWaiting,                        // WAITING        TS_WAIT      in Object.wait()
+  kWaitingForGcToComplete,         // WAITING        TS_WAIT      blocked waiting for GC
+  kWaitingPerformingGc,            // WAITING        TS_WAIT      performing GC
+  kWaitingForDebuggerSend,         // WAITING        TS_WAIT      blocked waiting for events to be sent
+  kWaitingForDebuggerToAttach,     // WAITING        TS_WAIT      blocked waiting for debugger to attach
+  kWaitingInMainDebuggerLoop,      // WAITING        TS_WAIT      blocking/reading/processing debugger events
+  kWaitingForDebuggerSuspension,   // WAITING        TS_WAIT      waiting for debugger suspend all
+  kWaitingForJniOnLoad,            // WAITING        TS_WAIT      waiting for execution of dlopen and JNI on load code
+  kWaitingForSignalCatcherOutput,  // WAITING        TS_WAIT      waiting for signal catcher IO to complete
+  kWaitingInMainSignalCatcherLoop, // WAITING        TS_WAIT      blocking/reading/processing signals
+  kStarting,                       // NEW            TS_WAIT      native thread started, not yet ready to run managed code
+  kNative,                         // RUNNABLE       TS_RUNNING   running in a JNI native method
+  kSuspended,                      // RUNNABLE       TS_RUNNING   suspended by GC or debugger
 };
 
 enum ThreadFlag {
diff --git a/test/ThreadStress/ThreadStress.java b/test/ThreadStress/ThreadStress.java
index 5389c20..8d8135d 100644
--- a/test/ThreadStress/ThreadStress.java
+++ b/test/ThreadStress/ThreadStress.java
@@ -34,7 +34,10 @@
         ALLOC(60),
         STACKTRACE(20),
         EXIT(50),
-        WAIT(50);
+
+        SLEEP(25),
+        TIMED_WAIT(10),
+        WAIT(15);
 
         private final int frequency;
         Operation(int frequency) {
@@ -48,7 +51,7 @@
         final int totalOperations = 1000;
         final int operationsPerThread = totalOperations/numberOfThreads;
 
-        // Lock used to notify threads performin Operation.WAIT
+        // Lock used to notify threads performing Operation.WAIT
         final Object lock = new Object();
 
         // Each thread is going to do operationsPerThread
@@ -203,11 +206,26 @@
                         } catch (ErrnoException ex) {
                         }
                     }
+                    case SLEEP: {
+                        try {
+                            Thread.sleep(100);
+                        } catch (InterruptedException ignored) {
+                        }
+                    }
+                    case TIMED_WAIT: {
+                        synchronized (lock) {
+                            try {
+                                lock.wait(100, 0);
+                            } catch (InterruptedException ignored) {
+                            }
+                        }
+                        break;
+                    }
                     case WAIT: {
                         synchronized (lock) {
                             try {
                                 lock.wait();
-                            } catch (InterruptedException e) {
+                            } catch (InterruptedException ignored) {
                             }
                         }
                         break;