Wire in the DDMS heap stuff.
(It's still UNIMPLEMENTED at the bottom, though.)
Change-Id: I0f4c1c90cafb48b045685ae67300170fd696f386
diff --git a/src/dalvik_system_VMDebug.cc b/src/dalvik_system_VMDebug.cc
index d5d0917..3c728f7 100644
--- a/src/dalvik_system_VMDebug.cc
+++ b/src/dalvik_system_VMDebug.cc
@@ -38,8 +38,8 @@
// TODO: we might need to uncomment these to make them work.
//features.push_back("method-trace-profiling");
//features.push_back("method-trace-profiling-streaming");
- //features.push_back("hprof-heap-dump");
- //features.push_back("hprof-heap-dump-streaming");
+ features.push_back("hprof-heap-dump");
+ features.push_back("hprof-heap-dump-streaming");
return toStringArray(env, features);
}
diff --git a/src/debugger.cc b/src/debugger.cc
index 2d9924d..bff410e 100644
--- a/src/debugger.cc
+++ b/src/debugger.cc
@@ -79,6 +79,13 @@
static bool gDdmThreadNotification = false;
+// DDMS GC-related settings.
+static Dbg::HpifWhen gDdmHpifWhen = Dbg::HPIF_WHEN_NEVER;
+static Dbg::HpsgWhen gDdmHpsgWhen = Dbg::HPSG_WHEN_NEVER;
+static Dbg::HpsgWhat gDdmHpsgWhat;
+static Dbg::HpsgWhen gDdmNhsgWhen = Dbg::HPSG_WHEN_NEVER;
+static Dbg::HpsgWhat gDdmNhsgWhat;
+
static ObjectRegistry* gRegistry = NULL;
/*
@@ -223,6 +230,21 @@
gRegistry = NULL;
}
+void Dbg::GcDidFinish() {
+ if (gDdmHpifWhen != HPIF_WHEN_NEVER) {
+ LOG(DEBUG) << "Sending VM heap info to DDM";
+ DdmSendHeapInfo(gDdmHpifWhen, false);
+ }
+ if (gDdmHpsgWhen != HPSG_WHEN_NEVER) {
+ LOG(DEBUG) << "Dumping VM heap to DDM";
+ DdmSendHeapSegments(false, false);
+ }
+ if (gDdmNhsgWhen != HPSG_WHEN_NEVER) {
+ LOG(DEBUG) << "Dumping native heap to DDM";
+ DdmSendHeapSegments(false, true);
+ }
+}
+
void Dbg::SetJdwpAllowed(bool allowed) {
gJdwpAllowed = allowed;
}
@@ -843,4 +865,48 @@
}
}
+int Dbg::DdmHandleHpifChunk(HpifWhen when) {
+ if (when == HPIF_WHEN_NOW) {
+ DdmSendHeapInfo(when, true);
+ return true;
+ }
+
+ if (when != HPIF_WHEN_NEVER && when != HPIF_WHEN_NEXT_GC && when != HPIF_WHEN_EVERY_GC) {
+ LOG(ERROR) << "invalid HpifWhen value: " << static_cast<int>(when);
+ return false;
+ }
+
+ gDdmHpifWhen = when;
+ return true;
+}
+
+bool Dbg::DdmHandleHpsgNhsgChunk(Dbg::HpsgWhen when, Dbg::HpsgWhat what, bool native) {
+ if (when != HPSG_WHEN_NEVER && when != HPSG_WHEN_EVERY_GC) {
+ LOG(ERROR) << "invalid HpsgWhen value: " << static_cast<int>(when);
+ return false;
+ }
+
+ if (what != HPSG_WHAT_MERGED_OBJECTS && what != HPSG_WHAT_DISTINCT_OBJECTS) {
+ LOG(ERROR) << "invalid HpsgWhat value: " << static_cast<int>(what);
+ return false;
+ }
+
+ if (native) {
+ gDdmNhsgWhen = when;
+ gDdmNhsgWhat = what;
+ } else {
+ gDdmHpsgWhen = when;
+ gDdmHpsgWhat = what;
+ }
+ return true;
+}
+
+void Dbg::DdmSendHeapInfo(HpifWhen reason, bool shouldLock) {
+ UNIMPLEMENTED(WARNING) << "reason=" << static_cast<int>(reason) << " shouldLock=" << shouldLock;
+}
+
+void Dbg::DdmSendHeapSegments(bool shouldLock, bool native) {
+ UNIMPLEMENTED(WARNING) << "shouldLock=" << shouldLock << " native=" << native;
+}
+
} // namespace art
diff --git a/src/debugger.h b/src/debugger.h
index 270b62a..a818a48 100644
--- a/src/debugger.h
+++ b/src/debugger.h
@@ -73,6 +73,9 @@
static void StartJdwp();
static void StopJdwp();
+ // Invoked by the GC in case we need to keep DDMS informed.
+ static void GcDidFinish();
+
// Return the DebugInvokeReq for the current thread.
static DebugInvokeReq* GetInvokeReq();
@@ -235,6 +238,27 @@
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);
+
+ enum HpifWhen {
+ HPIF_WHEN_NEVER = 0,
+ HPIF_WHEN_NOW = 1,
+ HPIF_WHEN_NEXT_GC = 2,
+ HPIF_WHEN_EVERY_GC = 3
+ };
+ static int DdmHandleHpifChunk(HpifWhen when);
+
+ enum HpsgWhen {
+ HPSG_WHEN_NEVER = 0,
+ HPSG_WHEN_EVERY_GC = 1,
+ };
+ enum HpsgWhat {
+ HPSG_WHAT_MERGED_OBJECTS = 0,
+ HPSG_WHAT_DISTINCT_OBJECTS = 1,
+ };
+ static bool DdmHandleHpsgNhsgChunk(HpsgWhen when, HpsgWhat what, bool native);
+
+ static void DdmSendHeapInfo(HpifWhen reason, bool shouldLock);
+ static void DdmSendHeapSegments(bool shouldLock, bool native);
};
#define CHUNK_TYPE(_name) \
diff --git a/src/heap.cc b/src/heap.cc
index 9e356d1..555569a 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -5,14 +5,15 @@
#include <limits>
#include <vector>
-#include "UniquePtr.h"
+#include "debugger.h"
#include "image.h"
#include "mark_sweep.h"
#include "object.h"
#include "space.h"
#include "stl_util.h"
-#include "timing_logger.h"
#include "thread_list.h"
+#include "timing_logger.h"
+#include "UniquePtr.h"
namespace art {
@@ -532,6 +533,7 @@
<< (num_bytes_allocated_/1024) << "KiB/" << (footprint/1024) << "KiB, "
<< "paused " << duration << "ms";
}
+ Dbg::GcDidFinish();
if (is_verbose_heap_) {
timings.Dump();
}
diff --git a/src/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc b/src/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc
index 4730127..4f06e68 100644
--- a/src/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc
+++ b/src/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc
@@ -154,21 +154,11 @@
}
static jint DdmVmInternal_heapInfoNotify(JNIEnv* env, jclass, jint when) {
- UNIMPLEMENTED(WARNING);
- return 0;
- //return dvmDdmHandleHpifChunk(when);
+ return Dbg::DdmHandleHpifChunk(static_cast<Dbg::HpifWhen>(when));
}
-/*
- * Enable DDM heap notifications.
- * @param when: 0=never (off), 1=during GC
- * @param what: 0=merged objects, 1=distinct objects
- * @param native: false=virtual heap, true=native heap
- */
static jboolean DdmVmInternal_heapSegmentNotify(JNIEnv* env, jclass, jint when, jint what, jboolean native) {
- UNIMPLEMENTED(WARNING);
- return JNI_FALSE;
- //return dvmDdmHandleHpsgNhsgChunk(when, what, native);
+ return Dbg::DdmHandleHpsgNhsgChunk(static_cast<Dbg::HpsgWhen>(when), static_cast<Dbg::HpsgWhat>(what), native);
}
static void DdmVmInternal_threadNotify(JNIEnv* env, jclass, jboolean enable) {