Merge "Take responsibility for translating thread states for managed code." into ics-mr1-plus-art
diff --git a/src/debugger.cc b/src/debugger.cc
index 569ea81..5a9a462 100644
--- a/src/debugger.cc
+++ b/src/debugger.cc
@@ -1388,17 +1388,16 @@
   // TODO: if we're in Thread.sleep(long), we should return TS_SLEEPING,
   // even if it's implemented using Object.wait(long).
   switch (thread->GetState()) {
-  case Thread::kTerminated:   *pThreadStatus = JDWP::TS_ZOMBIE;   break;
-  case Thread::kRunnable:     *pThreadStatus = JDWP::TS_RUNNING;  break;
-  case Thread::kTimedWaiting: *pThreadStatus = JDWP::TS_WAIT;     break;
-  case Thread::kBlocked:      *pThreadStatus = JDWP::TS_MONITOR;  break;
-  case Thread::kWaiting:      *pThreadStatus = JDWP::TS_WAIT;     break;
-  case Thread::kStarting:     *pThreadStatus = JDWP::TS_ZOMBIE;   break;
-  case Thread::kNative:       *pThreadStatus = JDWP::TS_RUNNING;  break;
-  case Thread::kVmWait:       *pThreadStatus = JDWP::TS_WAIT;     break;
-  case Thread::kSuspended:    *pThreadStatus = JDWP::TS_RUNNING;  break;
-  default:
-    LOG(FATAL) << "Unknown thread state " << thread->GetState();
+    case Thread::kTerminated:   *pThreadStatus = JDWP::TS_ZOMBIE;   break;
+    case Thread::kRunnable:     *pThreadStatus = JDWP::TS_RUNNING;  break;
+    case Thread::kTimedWaiting: *pThreadStatus = JDWP::TS_WAIT;     break;
+    case Thread::kBlocked:      *pThreadStatus = JDWP::TS_MONITOR;  break;
+    case Thread::kWaiting:      *pThreadStatus = JDWP::TS_WAIT;     break;
+    case Thread::kStarting:     *pThreadStatus = JDWP::TS_ZOMBIE;   break;
+    case Thread::kNative:       *pThreadStatus = JDWP::TS_RUNNING;  break;
+    case Thread::kVmWait:       *pThreadStatus = JDWP::TS_WAIT;     break;
+    case Thread::kSuspended:    *pThreadStatus = JDWP::TS_RUNNING;  break;
+    // Don't add a 'default' here so the compiler can spot incompatible enum changes.
   }
 
   *pSuspendStatus = (thread->IsSuspended() ? JDWP::SUSPEND_STATUS_SUSPENDED : JDWP::SUSPEND_STATUS_NOT_SUSPENDED);
diff --git a/src/java_lang_Thread.cc b/src/java_lang_Thread.cc
index 52c5378..6ce2609 100644
--- a/src/java_lang_Thread.cc
+++ b/src/java_lang_Thread.cc
@@ -45,13 +45,34 @@
   Thread::Create(managedThread, stackSize);
 }
 
-static jint Thread_nativeGetStatus(JNIEnv* env, jobject javaThread) {
+static jint Thread_nativeGetStatus(JNIEnv* env, jobject javaThread, jboolean hasBeenStarted) {
+  // Ordinals from Java's Thread.State.
+  const jint kJavaNew = 0;
+  const jint kJavaRunnable = 1;
+  const jint kJavaBlocked = 2;
+  const jint kJavaWaiting = 3;
+  const jint kJavaTimedWaiting = 4;
+  const jint kJavaTerminated = 5;
+
+  Thread::State internal_thread_state = (hasBeenStarted ? Thread::kTerminated : Thread::kStarting);
   ScopedThreadListLock thread_list_lock;
   Thread* thread = Thread::FromManagedThread(env, javaThread);
-  if (thread == NULL) {
-    return -1;
+  if (thread != NULL) {
+    internal_thread_state = thread->GetState();
   }
-  return static_cast<jint>(thread->GetState());
+  switch (internal_thread_state) {
+    case Thread::kTerminated:   return kJavaTerminated;
+    case Thread::kRunnable:     return kJavaRunnable;
+    case Thread::kTimedWaiting: return kJavaTimedWaiting;
+    case Thread::kBlocked:      return kJavaBlocked;
+    case Thread::kWaiting:      return kJavaWaiting;
+    case Thread::kStarting:     return kJavaNew;
+    case Thread::kNative:       return kJavaRunnable;
+    case Thread::kVmWait:       return kJavaWaiting;
+    case Thread::kSuspended:    return kJavaRunnable;
+    // Don't add a 'default' here so the compiler can spot incompatible enum changes.
+  }
+  return -1; // Unreachable.
 }
 
 static jboolean Thread_nativeHoldsLock(JNIEnv* env, jobject javaThread, jobject javaObject) {
@@ -115,7 +136,7 @@
   NATIVE_METHOD(Thread, interrupted, "()Z"),
   NATIVE_METHOD(Thread, isInterrupted, "()Z"),
   NATIVE_METHOD(Thread, nativeCreate, "(Ljava/lang/Thread;J)V"),
-  NATIVE_METHOD(Thread, nativeGetStatus, "()I"),
+  NATIVE_METHOD(Thread, nativeGetStatus, "(Z)I"),
   NATIVE_METHOD(Thread, nativeHoldsLock, "(Ljava/lang/Object;)Z"),
   NATIVE_METHOD(Thread, nativeInterrupt, "()V"),
   NATIVE_METHOD(Thread, nativeSetName, "(Ljava/lang/String;)V"),
diff --git a/src/thread.h b/src/thread.h
index 9de105e..32e000c 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -72,19 +72,17 @@
     kMaxPriority = 10,
   };
 
-  // Thread states. These must match Thread.STATE_MAP.
+  // Thread states.
   enum State {
-    // These correspond to JDWP states (but needn't share the same values).
-    kTerminated   = 0,        // TS_ZOMBIE
-    kRunnable     = 1,        // TS_RUNNING
-    kTimedWaiting = 2,        // TS_WAIT in Object.wait() with a timeout
-    kBlocked      = 3,        // TS_MONITOR on a monitor
-    kWaiting      = 4,        // TS_WAIT in Object.wait()
-    // Non-JDWP states.
-    kStarting     = 5,        // native thread started, not yet ready to run managed code
-    kNative       = 6,        // off in a JNI native method
-    kVmWait       = 7,        // waiting on an internal runtime resource
-    kSuspended    = 8,        // suspended, usually by GC or debugger
+    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()
+    kStarting     = 5, // Thread.NEW                            - native thread started, not yet ready to run managed code
+    kNative       = 6, //                                       - running in a JNI native method
+    kVmWait       = 7, //                                       - waiting on an internal runtime resource
+    kSuspended    = 8, //                                       - suspended by GC or debugger
   };
 
   // Space to throw a StackOverflowError in.