Wire up hprof.
I tested this with test 074-gc-thrash, which creates a .hprof file
that can be read with hat.
Change-Id: Ie75b7a7cf3c2ee32189df47ab0129e99449ebc6c
diff --git a/src/dalvik_system_VMDebug.cc b/src/dalvik_system_VMDebug.cc
index 3c728f7..7461fc4 100644
--- a/src/dalvik_system_VMDebug.cc
+++ b/src/dalvik_system_VMDebug.cc
@@ -17,6 +17,7 @@
#include "class_linker.h"
#include "debugger.h"
#include "jni_internal.h"
+#include "hprof/hprof.h"
#include "ScopedUtfChars.h"
#include "toStringArray.h"
@@ -196,8 +197,7 @@
}
}
- UNIMPLEMENTED(WARNING);
- int result = 0; //hprofDumpHeap(filename.c_str(), fd, false);
+ int result = hprof::hprofDumpHeap(filename.c_str(), fd, false);
if (result != 0) {
// TODO: ideally we'd throw something more specific based on actual failure
jniThrowException(env, "Ljava/lang/RuntimeException;", "Failure during heap dump; check log output for details");
@@ -207,7 +207,7 @@
void VMDebug_dumpHprofDataDdms(JNIEnv* env, jclass) {
UNIMPLEMENTED(WARNING);
- int result = 0; //hprofDumpHeap("[DDMS]", -1, true);
+ int result = hprof::hprofDumpHeap("[DDMS]", -1, true);
if (result != 0) {
// TODO: ideally we'd throw something more specific based on actual failure
jniThrowException(env, "Ljava/lang/RuntimeException;", "Failure during heap dump; check log output for details");
diff --git a/src/hprof/hprof.cc b/src/hprof/hprof.cc
index 9415549..a7047ac 100644
--- a/src/hprof/hprof.cc
+++ b/src/hprof/hprof.cc
@@ -269,6 +269,7 @@
CHECK(fileName != NULL);
ScopedHeapLock lock;
+ ScopedThreadStateChange tsc(Thread::Current(), Thread::kRunnable);
ThreadList* thread_list = Runtime::Current()->GetThreadList();
thread_list->SuspendAll();
diff --git a/src/hprof/hprof_class.cc b/src/hprof/hprof_class.cc
index 2e40ad4..e601e91 100644
--- a/src/hprof/hprof_class.cc
+++ b/src/hprof/hprof_class.cc
@@ -40,7 +40,7 @@
}
static int getPrettyClassNameId(Class* clazz) {
- return hprofLookupStringId(PrettyClass(clazz));
+ return hprofLookupStringId(PrettyDescriptor(clazz->GetDescriptor()));
}
hprof_class_object_id hprofLookupClassId(Class* clazz) {
@@ -63,6 +63,7 @@
*/
getPrettyClassNameId(clazz);
+ CHECK(present == clazz);
return (hprof_string_id) present;
}
diff --git a/src/hprof/hprof_heap.cc b/src/hprof/hprof_heap.cc
index 9545f7c..571167d 100644
--- a/src/hprof/hprof_heap.cc
+++ b/src/hprof/hprof_heap.cc
@@ -305,6 +305,8 @@
// aren't all the same size. But they're at least this
// size.
hprofAddU4ToRecord(rec, sizeof(Class)); // instance size
+ } else if (thisClass->IsArrayClass() || thisClass->IsPrimitive()) {
+ hprofAddU4ToRecord(rec, 0);
} else {
hprofAddU4ToRecord(rec, thisClass->GetObjectSize()); // instance size
}
@@ -346,7 +348,7 @@
/* Instance fields for this class (no superclass fields)
*/
- int iFieldCount = thisClass->NumInstanceFields();
+ int iFieldCount = thisClass->IsObjectClass() ? 0 : thisClass->NumInstanceFields();
hprofAddU2ToRecord(rec, (uint16_t)iFieldCount);
for (int i = 0; i < iFieldCount; ++i) {
Field* f = thisClass->GetInstanceField(i);
@@ -413,8 +415,6 @@
#endif
}
} else {
- const Class* sclass;
- size_t sizePatchOffset, savedLen;
/* obj is an instance object.
*/
@@ -427,14 +427,15 @@
* data, which we won't know until we're done writing
* it.
*/
- sizePatchOffset = rec->length;
+ size_t sizePatchOffset = rec->length;
hprofAddU4ToRecord(rec, 0x77777777);
/* Write the instance data; fields for this
* class, followed by super class fields, and so on.
+ * Don't write the klass or monitor fields of Object.class.
*/
- sclass = clazz;
- while (sclass != NULL) {
+ const Class* sclass = clazz;
+ while (!sclass->IsObjectClass()) {
int ifieldCount = sclass->NumInstanceFields();
for (int i = 0; i < ifieldCount; i++) {
Field* f = sclass->GetInstanceField(i);
@@ -459,7 +460,7 @@
/* Patch the instance field length.
*/
- savedLen = rec->length;
+ size_t savedLen = rec->length;
rec->length = sizePatchOffset;
hprofAddU4ToRecord(rec, savedLen - (sizePatchOffset + 4));
rec->length = savedLen;
diff --git a/src/hprof/hprof_string.cc b/src/hprof/hprof_string.cc
index f498b6d..bc1caf2 100644
--- a/src/hprof/hprof_string.cc
+++ b/src/hprof/hprof_string.cc
@@ -25,7 +25,7 @@
namespace hprof {
-size_t next_string_id_ = 200001;
+size_t next_string_id_ = 0x400000;
typedef std::tr1::unordered_map<std::string, size_t> StringMap;
typedef std::tr1::unordered_map<std::string, size_t>::iterator StringMapIterator;
static Mutex strings_lock_("hprof strings");
@@ -60,7 +60,7 @@
hprof_record_t *rec = &ctx->curRec;
- for (StringMapIterator it = strings_.begin(); it != strings_.end(); ++it) {
+ for (StringMapIterator it = strings_.begin(); it != strings_.end(); ++it) {
std::string string = (*it).first;
size_t id = (*it).second;
diff --git a/src/object.h b/src/object.h
index 6610871..dd2c1ca 100644
--- a/src/object.h
+++ b/src/object.h
@@ -1504,10 +1504,10 @@
}
size_t GetObjectSize() const {
- CHECK(!IsVariableSize());
+ CHECK(!IsVariableSize()) << " class=" << PrettyTypeOf(this);
DCHECK_EQ(sizeof(size_t), sizeof(int32_t));
size_t result = GetField32(OFFSET_OF_OBJECT_MEMBER(Class, object_size_), false);
- CHECK_GE(result, sizeof(Object));
+ CHECK_GE(result, sizeof(Object)) << " class=" << PrettyTypeOf(this);
return result;
}