summaryrefslogtreecommitdiffstats
path: root/vm/hprof/Hprof.c
diff options
context:
space:
mode:
Diffstat (limited to 'vm/hprof/Hprof.c')
-rw-r--r--vm/hprof/Hprof.c87
1 files changed, 86 insertions, 1 deletions
diff --git a/vm/hprof/Hprof.c b/vm/hprof/Hprof.c
index 28f81c778..5cd5136c2 100644
--- a/vm/hprof/Hprof.c
+++ b/vm/hprof/Hprof.c
@@ -21,7 +21,10 @@
* heap, and some analysis tools require that the class and string data
* appear first.
*/
+
#include "Hprof.h"
+#include "alloc/HeapInternal.h"
+#include "alloc/Visit.h"
#include <string.h>
#include <unistd.h>
@@ -30,7 +33,6 @@
#include <sys/time.h>
#include <time.h>
-
#define kHeadSuffix "-hptemp"
hprof_context_t *
@@ -183,3 +185,86 @@ hprofFreeContext(hprof_context_t *ctx)
free(ctx->fileDataPtr);
free(ctx);
}
+
+/*
+ * Visitor invoked on every root reference.
+ */
+static void hprofRootVisitor(void *addr, u4 threadId, RootType type, void *arg)
+{
+ static const hprof_heap_tag_t xlate[] = {
+ HPROF_ROOT_UNKNOWN,
+ HPROF_ROOT_JNI_GLOBAL,
+ HPROF_ROOT_JNI_LOCAL,
+ HPROF_ROOT_JAVA_FRAME,
+ HPROF_ROOT_NATIVE_STACK,
+ HPROF_ROOT_STICKY_CLASS,
+ HPROF_ROOT_THREAD_BLOCK,
+ HPROF_ROOT_MONITOR_USED,
+ HPROF_ROOT_THREAD_OBJECT,
+ HPROF_ROOT_INTERNED_STRING,
+ HPROF_ROOT_FINALIZING,
+ HPROF_ROOT_DEBUGGER,
+ HPROF_ROOT_REFERENCE_CLEANUP,
+ HPROF_ROOT_VM_INTERNAL,
+ HPROF_ROOT_JNI_MONITOR,
+ };
+ hprof_context_t *ctx;
+
+ assert(arg != NULL);
+ assert(type < NELEM(xlate));
+ ctx = arg;
+ ctx->gcScanState = xlate[type];
+ ctx->gcThreadSerialNumber = threadId;
+ hprofMarkRootObject(ctx, addr, 0);
+ ctx->gcScanState = 0;
+ ctx->gcThreadSerialNumber = 0;
+}
+
+/*
+ * Visitor invoked on every heap object.
+ */
+static void hprofBitmapCallback(void *ptr, void *arg)
+{
+ Object *obj;
+ hprof_context_t *ctx;
+
+ assert(ptr != NULL);
+ assert(arg != NULL);
+ obj = ptr;
+ ctx = arg;
+ hprofDumpHeapObject(ctx, obj);
+}
+
+/*
+ * Walk the roots and heap writing heap information to the specified
+ * file.
+ *
+ * If "fd" is >= 0, the output will be written to that file descriptor.
+ * Otherwise, "fileName" is used to create an output file.
+ *
+ * If "directToDdms" is set, the other arguments are ignored, and data is
+ * sent directly to DDMS.
+ *
+ * Returns 0 on success, or an error code on failure.
+ */
+int hprofDumpHeap(const char* fileName, int fd, bool directToDdms)
+{
+ hprof_context_t *ctx;
+ int success;
+
+ assert(fileName != NULL);
+ dvmLockHeap();
+ dvmSuspendAllThreads(SUSPEND_FOR_HPROF);
+ ctx = hprofStartup(fileName, fd, directToDdms);
+ if (ctx == NULL) {
+ return -1;
+ }
+ dvmVisitRoots(hprofRootVisitor, ctx);
+ dvmHeapBitmapWalk(dvmHeapSourceGetLiveBits(), hprofBitmapCallback, ctx);
+ hprofFinishHeapDump(ctx);
+//TODO: write a HEAP_SUMMARY record
+ success = hprofShutdown(ctx) ? 0 : -1;
+ dvmSuspendAllThreads(SUSPEND_FOR_HPROF);
+ dvmUnlockHeap();
+ return success;
+}