Implement thread name change notification for DDMS.
Change-Id: If63d89991951989f27ee267895244e115661dce9
diff --git a/src/debugger.cc b/src/debugger.cc
index 828ee4a..d8f58da 100644
--- a/src/debugger.cc
+++ b/src/debugger.cc
@@ -791,42 +791,43 @@
}
/*
- * Send a notification when a thread starts or stops.
+ * Send a notification when a thread starts, stops, or changes its name.
*
* Because we broadcast the full set of threads when the notifications are
* first enabled, it's possible for "thread" to be actively executing.
*/
-void DdmSendThreadNotification(Thread* t, bool started) {
+void Dbg::DdmSendThreadNotification(Thread* t, uint32_t type) {
if (!gDdmThreadNotification) {
return;
}
- if (started) {
- SirtRef<String> name(t->GetName());
- size_t char_count = (name.get() != NULL) ? name->GetLength() : 0;
-
- size_t byte_count = char_count*2 + sizeof(uint32_t)*2;
- std::vector<uint8_t> buf(byte_count);
- JDWP::Set4BE(&buf[0], t->GetThinLockId());
- JDWP::Set4BE(&buf[4], char_count);
- if (char_count > 0) {
- // Copy the UTF-16 string, transforming to big-endian.
- const jchar* src = name->GetCharArray()->GetData();
- jchar* dst = reinterpret_cast<jchar*>(&buf[8]);
- while (char_count--) {
- JDWP::Set2BE(reinterpret_cast<uint8_t*>(dst++), *src++);
- }
- }
- Dbg::DdmSendChunk(CHUNK_TYPE("THCR"), buf.size(), &buf[0]);
- } else {
+ if (type == CHUNK_TYPE("THDE")) {
uint8_t buf[4];
JDWP::Set4BE(&buf[0], t->GetThinLockId());
Dbg::DdmSendChunk(CHUNK_TYPE("THDE"), 4, buf);
+ } else {
+ CHECK(type == CHUNK_TYPE("THCR") || type == CHUNK_TYPE("THNM")) << type;
+ SirtRef<String> name(t->GetName());
+ size_t char_count = (name.get() != NULL) ? name->GetLength() : 0;
+ const jchar* chars = name->GetCharArray()->GetData();
+
+ size_t byte_count = char_count*2 + sizeof(uint32_t)*2;
+ std::vector<uint8_t> bytes(byte_count);
+ uint8_t* dst = &bytes[0];
+ JDWP::Write4BE(&dst, t->GetThinLockId());
+ JDWP::Write4BE(&dst, char_count);
+ if (char_count > 0) {
+ // Copy the UTF-16 string, transforming to big-endian.
+ while (char_count--) {
+ JDWP::Write2BE(&dst, *chars++);
+ }
+ }
+ Dbg::DdmSendChunk(type, bytes.size(), &bytes[0]);
}
}
void DdmSendThreadStartCallback(Thread* t, void*) {
- DdmSendThreadNotification(t, true);
+ Dbg::DdmSendThreadNotification(t, CHUNK_TYPE("THCR"));
}
void Dbg::DdmSetThreadNotification(bool enable) {
@@ -841,23 +842,23 @@
}
}
-void PostThreadStartOrStop(Thread* t, bool is_start) {
+void PostThreadStartOrStop(Thread* t, uint32_t type) {
if (gDebuggerActive) {
JDWP::ObjectId id = gRegistry->Add(t->GetPeer());
- gJdwpState->PostThreadChange(id, is_start);
+ gJdwpState->PostThreadChange(id, type == CHUNK_TYPE("THCR"));
}
- DdmSendThreadNotification(t, is_start);
+ Dbg::DdmSendThreadNotification(t, type);
}
void Dbg::PostThreadStart(Thread* t) {
- PostThreadStartOrStop(t, true);
+ PostThreadStartOrStop(t, CHUNK_TYPE("THCR"));
}
void Dbg::PostThreadDeath(Thread* t) {
- PostThreadStartOrStop(t, false);
+ PostThreadStartOrStop(t, CHUNK_TYPE("THDE"));
}
-void Dbg::DdmSendChunk(int type, size_t byte_count, const uint8_t* buf) {
+void Dbg::DdmSendChunk(uint32_t type, size_t byte_count, const uint8_t* buf) {
CHECK(buf != NULL);
iovec vec[1];
vec[0].iov_base = reinterpret_cast<void*>(const_cast<uint8_t*>(buf));
@@ -865,7 +866,7 @@
Dbg::DdmSendChunkV(type, vec, 1);
}
-void Dbg::DdmSendChunkV(int type, const struct iovec* iov, int iovcnt) {
+void Dbg::DdmSendChunkV(uint32_t type, const struct iovec* iov, int iovcnt) {
if (gJdwpState == NULL) {
LOG(VERBOSE) << "Debugger thread not active, ignoring DDM send: " << type;
} else {
@@ -977,7 +978,7 @@
uint8_t* p;
uint8_t* pieceLenField;
size_t totalAllocationUnits;
- int type;
+ uint32_t type;
bool merge;
bool needHeader;
diff --git a/src/debugger.h b/src/debugger.h
index b85a65d..7ae6609 100644
--- a/src/debugger.h
+++ b/src/debugger.h
@@ -232,12 +232,13 @@
/*
* DDM support.
*/
+ static void DdmSendThreadNotification(Thread* t, uint32_t type);
static void DdmSetThreadNotification(bool enable);
static bool DdmHandlePacket(const uint8_t* buf, int dataLen, uint8_t** pReplyBuf, int* pReplyLen);
static void DdmConnected();
static void DdmDisconnected();
- static void DdmSendChunk(int type, size_t len, const uint8_t* buf);
- static void DdmSendChunkV(int type, const struct iovec* iov, int iovcnt);
+ static void DdmSendChunk(uint32_t type, size_t len, const uint8_t* buf);
+ static void DdmSendChunkV(uint32_t type, const struct iovec* iov, int iovcnt);
enum HpifWhen {
HPIF_WHEN_NEVER = 0,
@@ -262,7 +263,7 @@
};
#define CHUNK_TYPE(_name) \
- ((_name)[0] << 24 | (_name)[1] << 16 | (_name)[2] << 8 | (_name)[3])
+ static_cast<uint32_t>((_name)[0] << 24 | (_name)[1] << 16 | (_name)[2] << 8 | (_name)[3])
} // namespace art
diff --git a/src/java_lang_Thread.cc b/src/java_lang_Thread.cc
index 9031471..46b6241 100644
--- a/src/java_lang_Thread.cc
+++ b/src/java_lang_Thread.cc
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include "debugger.h"
#include "jni_internal.h"
#include "object.h"
#include "ScopedUtfChars.h"
@@ -74,20 +75,13 @@
}
}
-void Thread_nativeSetName(JNIEnv* env, jobject javaThread, jstring javaName) {
+void Thread_nativeSetName(JNIEnv* env, jobject javaThread, jstring) {
ScopedThreadListLock thread_list_lock;
Thread* thread = Thread::FromManagedThread(env, javaThread);
- if (thread != NULL) {
- ScopedUtfChars name(env, javaName);
- if (name.c_str() == NULL) {
- return;
- }
- LOG(INFO) << "Thread " << *thread << " changing name to '" << name.c_str() << "'";
- // TODO: needed for debugging (DDMS) support.
- //StringObject* nameStr = (StringObject*) dvmDecodeIndirectRef(env, javaName);
- //int threadId = (thread != NULL) ? thread->threadId : -1;
- //dvmDdmSendThreadNameChange(threadId, nameStr);
+ if (thread == NULL) {
+ return;
}
+ Dbg::DdmSendThreadNotification(thread, CHUNK_TYPE("THNM"));
}
/*
diff --git a/src/jdwp/jdwp.h b/src/jdwp/jdwp.h
index 2eae216..6f9625f 100644
--- a/src/jdwp/jdwp.h
+++ b/src/jdwp/jdwp.h
@@ -210,7 +210,7 @@
/*
* Send up a chunk of DDM data.
*/
- void DdmSendChunkV(int type, const iovec* iov, int iovcnt);
+ void DdmSendChunkV(uint32_t type, const iovec* iov, int iovcnt);
/*
* Process a request from the debugger.
diff --git a/src/jdwp/jdwp_event.cc b/src/jdwp/jdwp_event.cc
index 7d341d8..6b5ef8c 100644
--- a/src/jdwp/jdwp_event.cc
+++ b/src/jdwp/jdwp_event.cc
@@ -1146,7 +1146,7 @@
* other debugger traffic, and can't suspend the VM, so we skip all of
* the fun event token gymnastics.
*/
-void JdwpState::DdmSendChunkV(int type, const iovec* iov, int iovcnt) {
+void JdwpState::DdmSendChunkV(uint32_t type, const iovec* iov, int iovcnt) {
uint8_t header[kJDWPHeaderLen + 8];
size_t dataLen = 0;
diff --git a/src/jni_internal.cc b/src/jni_internal.cc
index 45eedb8..5787c65 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -79,7 +79,6 @@
locals.Dump();
LOG(FATAL) << "Failed adding to JNI local reference table "
<< "(has " << locals.Capacity() << " entries)";
- // TODO: dvmDumpThread(dvmThreadSelf(), false);
}
#if 0 // TODO: fix this to understand PushLocalFrame, so we can turn it on.
@@ -89,8 +88,7 @@
LOG(WARNING) << "Warning: more than 16 JNI local references: "
<< entry_count << " (most recent was a " << PrettyTypeOf(obj) << ")";
locals.Dump();
- // TODO: dvmDumpThread(dvmThreadSelf(), false);
- // dvmAbort();
+ // TODO: LOG(FATAL) instead.
}
}
#endif