ART: Add Thread start VLOG

Add a stack trace at the time of thread creation or attaching to
the verbose:threads logging.

Change-Id: I5e07c81ce24f145c37ab172eda7bb4c54dad4445
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 37a86f1..6656fe5 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -388,6 +388,24 @@
 void Thread::CreateNativeThread(JNIEnv* env, jobject java_peer, size_t stack_size, bool is_daemon) {
   CHECK(java_peer != nullptr);
   Thread* self = static_cast<JNIEnvExt*>(env)->self;
+
+  if (VLOG_IS_ON(threads)) {
+    ScopedObjectAccess soa(env);
+
+    ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_Thread_name);
+    mirror::String* java_name = reinterpret_cast<mirror::String*>(f->GetObject(
+        soa.Decode<mirror::Object*>(java_peer)));
+    std::string thread_name;
+    if (java_name != nullptr) {
+      thread_name = java_name->ToModifiedUtf8();
+    } else {
+      thread_name = "(Unnamed)";
+    }
+
+    VLOG(threads) << "Creating native thread for " << thread_name;
+    self->Dump(LOG(INFO));
+  }
+
   Runtime* runtime = Runtime::Current();
 
   // Atomically start the birth of the thread ensuring the runtime isn't shutting down.
@@ -556,6 +574,16 @@
     }
   }
 
+  if (VLOG_IS_ON(threads)) {
+    if (thread_name != nullptr) {
+      VLOG(threads) << "Attaching thread " << thread_name;
+    } else {
+      VLOG(threads) << "Attaching unnamed thread.";
+    }
+    ScopedObjectAccess soa(self);
+    self->Dump(LOG(INFO));
+  }
+
   {
     ScopedObjectAccess soa(self);
     Dbg::PostThreadStart(self);