Merge "Quick compiler: tighten null/0/0.0 workaround" into dalvik-dev
diff --git a/src/debugger.cc b/src/debugger.cc
index 42c0c7f..e0e02cf 100644
--- a/src/debugger.cc
+++ b/src/debugger.cc
@@ -1230,9 +1230,11 @@
   } else {
     if (f->IsStatic()) {
       LOG(WARNING) << "Ignoring non-NULL receiver for ObjectReference.SetValues on static field " << PrettyField(f);
-      o = NULL;
     }
   }
+  if (f->IsStatic()) {
+    o = f->GetDeclaringClass();
+  }
 
   JDWP::JdwpTag tag = BasicTagFromDescriptor(FieldHelper(f).GetTypeDescriptor());
 
@@ -1284,9 +1286,11 @@
   } else {
     if (f->IsStatic()) {
       LOG(WARNING) << "Ignoring non-NULL receiver for ObjectReference.SetValues on static field " << PrettyField(f);
-      o = NULL;
     }
   }
+  if (f->IsStatic()) {
+    o = f->GetDeclaringClass();
+  }
 
   JDWP::JdwpTag tag = BasicTagFromDescriptor(FieldHelper(f).GetTypeDescriptor());
 
@@ -1393,15 +1397,15 @@
 
 JDWP::ObjectId Dbg::GetSystemThreadGroupId() {
   ScopedObjectAccessUnchecked soa(Thread::Current());
-  Object* group =
-      soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_systemThreadGroup)->GetObject(NULL);
+  Field* f = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_systemThreadGroup);
+  Object* group = f->GetObject(f->GetDeclaringClass());
   return gRegistry->Add(group);
 }
 
 JDWP::ObjectId Dbg::GetMainThreadGroupId() {
   ScopedObjectAccess soa(Thread::Current());
-  Object* group =
-      soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_mainThreadGroup)->GetObject(NULL);
+  Field* f = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_mainThreadGroup);
+  Object* group = f->GetObject(f->GetDeclaringClass());
   return gRegistry->Add(group);
 }
 
@@ -1476,10 +1480,10 @@
 void Dbg::GetThreads(JDWP::ObjectId thread_group_id, std::vector<JDWP::ObjectId>& thread_ids) {
   class ThreadListVisitor {
    public:
-    ThreadListVisitor(const ScopedObjectAccessUnchecked& soa, Object* thread_group,
+    ThreadListVisitor(const ScopedObjectAccessUnchecked& soa, Object* desired_thread_group,
                       std::vector<JDWP::ObjectId>& thread_ids)
         SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-        : soa_(soa), thread_group_(thread_group), thread_ids_(thread_ids) {}
+        : soa_(soa), desired_thread_group_(desired_thread_group), thread_ids_(thread_ids) {}
 
     static void Visit(Thread* t, void* arg) {
       reinterpret_cast<ThreadListVisitor*>(arg)->Visit(t);
@@ -1493,20 +1497,33 @@
         // query all threads, so it's easier if we just don't tell them about this thread.
         return;
       }
-      bool should_add = (thread_group_ == NULL);
       Object* peer = soa_.Decode<Object*>(t->GetPeer());
-      if (!should_add) {
-        Object* group = soa_.DecodeField(WellKnownClasses::java_lang_Thread_group)->GetObject(peer);
-        should_add = (group == thread_group_);
-      }
-      if (should_add) {
+      if (IsInDesiredThreadGroup(peer)) {
         thread_ids_.push_back(gRegistry->Add(peer));
       }
     }
 
    private:
+    bool IsInDesiredThreadGroup(Object* peer)
+        SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+      // Do we want threads from all thread groups?
+      if (desired_thread_group_ == NULL) {
+        return true;
+      }
+      // peer might be NULL if the thread is still starting up.
+      if (peer == NULL) {
+        // We can't tell the debugger about this thread yet.
+        // TODO: if we identified threads to the debugger by their Thread*
+        // rather than their peer's Object*, we could fix this.
+        // Doing so might help us report ZOMBIE threads too.
+        return false;
+      }
+      Object* group = soa_.DecodeField(WellKnownClasses::java_lang_Thread_group)->GetObject(peer);
+      return (group == desired_thread_group_);
+    }
+
     const ScopedObjectAccessUnchecked& soa_;
-    Object* const thread_group_;
+    Object* const desired_thread_group_;
     std::vector<JDWP::ObjectId>& thread_ids_;
   };
 
diff --git a/src/jdwp/jdwp_main.cc b/src/jdwp/jdwp_main.cc
index 5e368e7..0691515 100644
--- a/src/jdwp/jdwp_main.cc
+++ b/src/jdwp/jdwp_main.cc
@@ -87,7 +87,7 @@
 
 JdwpState::JdwpState(const JdwpOptions* options)
     : options_(options),
-      thread_start_lock_("JDWP thread start lock"),
+      thread_start_lock_("JDWP thread start lock", kJdwpStartLock),
       thread_start_cond_("JDWP thread start condition variable", thread_start_lock_),
       pthread_(0),
       thread_(NULL),
@@ -96,7 +96,7 @@
       run(false),
       transport_(NULL),
       netState(NULL),
-      attach_lock_("JDWP attach lock"),
+      attach_lock_("JDWP attach lock", kJdwpAttachLock),
       attach_cond_("JDWP attach condition variable", attach_lock_),
       last_activity_time_ms_(0),
       serial_lock_("JDWP serial lock", kJdwpSerialLock),
@@ -161,7 +161,6 @@
       state->thread_start_cond_.Wait(self);
     } else {
       {
-        MutexLock attach_locker(self, state->attach_lock_);
         /*
          * We have bound to a port, or are trying to connect outbound to a
          * debugger.  Create the JDWP thread and let it continue the mission.
@@ -184,6 +183,7 @@
          */
         {
           ScopedThreadStateChange tsc(self, kWaitingForDebuggerToAttach);
+          MutexLock attach_locker(self, state->attach_lock_);
           state->attach_cond_.Wait(self);
         }
       }
diff --git a/src/locks.h b/src/locks.h
index cd2f8b7..c009f1d 100644
--- a/src/locks.h
+++ b/src/locks.h
@@ -37,17 +37,19 @@
   kThreadSuspendCountLock = 2,
   kAbortLock = 3,
   kDefaultMutexLevel = 4,
-  kJdwpSerialLock = 5,
-  kAllocSpaceLock = 6,
-  kLoadLibraryLock = 7,
-  kClassLinkerClassesLock = 8,
-  kThreadListLock = 9,
-  kRuntimeShutdownLock = 10,
-  kHeapBitmapLock = 11,
-  kMonitorLock = 12,
-  kMutatorLock = 13,
-  kZygoteCreationLock = 14,
-  kMaxMutexLevel = kMutatorLock,
+  kJdwpAttachLock = 5,
+  kJdwpStartLock = 6,
+  kJdwpSerialLock = 7,
+  kAllocSpaceLock = 8,
+  kLoadLibraryLock = 9,
+  kClassLinkerClassesLock = 10,
+  kThreadListLock = 11,
+  kRuntimeShutdownLock = 12,
+  kHeapBitmapLock = 13,
+  kMonitorLock = 14,
+  kMutatorLock = 15,
+  kZygoteCreationLock = 16,
+  kMaxMutexLevel = kZygoteCreationLock,
 };
 std::ostream& operator<<(std::ostream& os, const LockLevel& rhs);
 
diff --git a/src/mutex.cc b/src/mutex.cc
index c09a4a0..16811d3 100644
--- a/src/mutex.cc
+++ b/src/mutex.cc
@@ -158,7 +158,7 @@
     return;
   }
   if (level_ != kMonitorLock) {
-    if (kDebugLocking) {
+    if (kDebugLocking && !gAborting) {
       CHECK(self->GetHeldMutex(level_) == this) << "Unlocking on unacquired mutex: " << name_;
     }
     self->SetHeldMutex(level_, NULL);