diff memory_profiler.cpp @ 57:1fd63ee398dc

Added some really terrible code that adds a 'children' array property to object info.
author Atul Varma <varmaa@toolness.com>
date Wed, 24 Jun 2009 19:38:05 -0700
parents b36c15de56f6
children 0b66a265df13
line wrap: on
line diff
--- a/memory_profiler.cpp	Wed Jun 24 18:36:24 2009 -0700
+++ b/memory_profiler.cpp	Wed Jun 24 19:38:05 2009 -0700
@@ -49,9 +49,6 @@
   // Whether the tracing operation is successful or failed.
   JSBool result;
 
-  // Class to look for.
-  JSClass *classp;
-
   // Runtime that we're tracing.
   JSRuntime *runtime;
 
@@ -62,9 +59,32 @@
 // Static singleton for tracking the state of tracing the JS heap.
 static TracingState tracingState;
 
-// JSTraceCallback for heap dumping and other operations.
+typedef struct ChildTracingState {
+  int num;
+  void **things;
+  uint32 *kinds;
+  JSTracer tracer;
+};
+
+static ChildTracingState childTracingState;
 
-static void traceCallback(JSTracer *trc, void *thing, uint32 kind)
+// JSTraceCallback to build a hashtable of children.
+static void childCountBuilder(JSTracer *trc, void *thing, uint32 kind)
+{
+  childTracingState.num++;
+}
+
+// JSTraceCallback to build a hashtable of children.
+static void childBuilder(JSTracer *trc, void *thing, uint32 kind)
+{
+  *childTracingState.kinds = kind;
+  childTracingState.kinds++;
+  *childTracingState.things = thing;
+  childTracingState.things++;
+}
+
+// JSTraceCallback to build a hashtable of existing object references.
+static void visitedBuilder(JSTracer *trc, void *thing, uint32 kind)
 {
   switch (kind) {
   case JSTRACE_OBJECT:
@@ -105,6 +125,49 @@
   return JS_MAP_GCROOT_NEXT;
 }
 
+static JSBool getChildrenInfo(JSContext *cx, JSObject *info,
+                              JSObject *target, JSContext *targetCx)
+{
+  childTracingState.tracer.context = targetCx;
+  childTracingState.tracer.callback = childCountBuilder;
+  childTracingState.num = 0;
+  JS_TraceChildren(&childTracingState.tracer, target, JSTRACE_OBJECT);
+
+  void *things[childTracingState.num];
+  uint32 kinds[childTracingState.num];
+
+  childTracingState.things = things;
+  childTracingState.kinds = kinds;
+
+  childTracingState.tracer.callback = childBuilder;
+  JS_TraceChildren(&childTracingState.tracer, target, JSTRACE_OBJECT);
+
+  int numObjectChildren = 0;
+  for (int i = 0; i < childTracingState.num; i++) {
+    if (kinds[i] == JSTRACE_OBJECT)
+      numObjectChildren++;
+  }
+
+  jsval childrenVals[numObjectChildren];
+
+  int currChild = 0;
+  for (int i = 0; i < childTracingState.num; i++) {
+    if (kinds[i] == JSTRACE_OBJECT) {
+      childrenVals[currChild] = INT_TO_JSVAL((unsigned int) things[i]);
+      currChild += 1;
+    }
+  }
+
+  JSObject *children = JS_NewArrayObject(cx, numObjectChildren, childrenVals);
+  if (children == NULL) {
+    JS_ReportOutOfMemory(cx);
+    return JS_FALSE;
+  }
+
+  return JS_DefineProperty(cx, info, "children", OBJECT_TO_JSVAL(children),
+                           NULL, NULL, JSPROP_ENUMERATE);
+}
+
 static JSBool getObjInfo(JSContext *cx, JSObject *obj, uintN argc,
                          jsval *argv, jsval *rval)
 {
@@ -150,6 +213,9 @@
       return JS_FALSE;
     }
 
+    if (!getChildrenInfo(cx, info, target, targetCx))
+      return JS_FALSE;
+
     *rval = OBJECT_TO_JSVAL(info);
   } else
     *rval = JSVAL_NULL;
@@ -197,7 +263,7 @@
   tracingState.runtime = JS_GetRuntime(cx);
   tracingState.result = JS_TRUE;
   tracingState.tracer.context = cx;
-  tracingState.tracer.callback = traceCallback;
+  tracingState.tracer.callback = visitedBuilder;
   JS_TraceRuntime(&tracingState.tracer);
 
   if (!tracingState.result)