changeset 37:193ff16b013a

Added a dumpHeap() function to the TCB global object, which can be used even w/o debug builds of SpiderMonkey.
author Atul Varma <varmaa@toolness.com>
date Mon, 22 Jun 2009 17:24:18 -0700
parents be05a91e7b0a
children cfdbaadf21b8
files spidermonkey-playground.cpp
diffstat 1 files changed, 75 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/spidermonkey-playground.cpp	Mon Jun 22 15:54:37 2009 -0700
+++ b/spidermonkey-playground.cpp	Mon Jun 22 17:24:18 2009 -0700
@@ -41,6 +41,7 @@
 #include "string.h"
 #include "jsapi.h"
 #include "jsdbgapi.h"
+#include "jsdhash.h"
 
 #include "wrapper.h"
 
@@ -80,6 +81,79 @@
   return JS_TRUE;
 }
 
+// Private structure to track the state of tracing the JS heap.
+
+typedef struct TracingState {
+  // Keeps track of what objects we've visited so far.
+  JSDHashTable visited;
+
+  // Whether the tracing operation is successful or failed.
+  JSBool result;
+};
+
+// Static singleton for tracking the state of tracing the JS heap.
+static TracingState tracingState;
+
+// JSTraceCallback for heap dumping and other operations.
+
+static void traceCallback(JSTracer *trc, void *thing, uint32 kind)
+{
+  switch (kind) {
+  case JSTRACE_OBJECT:
+    JSDHashEntryStub *entry = (JSDHashEntryStub *)
+      JS_DHashTableOperate(&tracingState.visited,
+                           thing,
+                           JS_DHASH_LOOKUP);
+    if (JS_DHASH_ENTRY_IS_FREE((JSDHashEntryHdr *)entry)) {
+      entry = (JSDHashEntryStub *) JS_DHashTableOperate(&tracingState.visited,
+                                                        thing,
+                                                        JS_DHASH_ADD);
+      if (entry == NULL) {
+        JS_ReportOutOfMemory(trc->context);
+        tracingState.result = JS_FALSE;
+        return;
+      }
+      entry->key = thing;
+      JS_TraceChildren(trc, thing, kind);
+    }
+    break;
+  case JSTRACE_DOUBLE:
+    break;
+  case JSTRACE_STRING:
+    const char *str = JS_GetStringBytes((JSString *)thing);
+    printf("string: %s\n", str);
+    break;
+  }
+}
+
+// This native JS function dumps the heap to stdout. It's available even on
+// non-debug builds of SpiderMonkey, but it's also not terribly robust.
+
+static JSBool dumpHeap(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+                       jsval *rval)
+{
+  JSTracer tracer;
+
+  if (!JS_DHashTableInit(&tracingState.visited, JS_DHashGetStubOps(),
+                         NULL, sizeof(JSDHashEntryStub),
+                         JS_DHASH_DEFAULT_CAPACITY(100))) {
+    JS_ReportOutOfMemory(cx);
+    return JS_FALSE;
+  }
+
+  tracingState.result = JS_TRUE;
+  tracer.context = cx;
+  tracer.callback = traceCallback;
+  JS_TraceRuntime(&tracer);
+
+  JS_DHashTableFinish(&tracingState.visited);
+
+  if (!tracingState.result)
+    return JS_FALSE;
+  *rval = JSVAL_VOID;
+  return JS_TRUE;
+}
+
 // This native JS function forces garbage collection.
 
 static JSBool forceGC(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
@@ -378,6 +452,7 @@
   JS_FS("functionInfo",   functionInfo,   1, 0, 0),
   JS_FS("enumerate",      enumerate,      1, 0, 0),
   JS_FS("forceGC",        forceGC,        0, 0, 0),
+  JS_FS("dumpHeap",       dumpHeap,       0, 0, 0),
   JS_FS_END
 };