diff options
author | Giovanni Campagna <gcampagna@src.gnome.org> | 2012-07-04 22:32:03 +0200 |
---|---|---|
committer | Giovanni Campagna <gcampagna@src.gnome.org> | 2012-10-30 17:23:36 +0100 |
commit | 83a6e435711091b98990c311cd8c1d55bcc834cb (patch) | |
tree | 7711f2b3ff04e921daf411f08116675e4280176a | |
parent | d10cdb471bd101065961bb2b6321630ca15ef356 (diff) | |
download | gjs-83a6e435711091b98990c311cd8c1d55bcc834cb.tar.gz |
Keep Alive: add a debugging method to print all active roots
Adds a print_roots() to keep-alive objects (such as
__gc_this_on_context_destroy, where GObjects are stored), which
prints a dump of all objects known to it on stderr.
This is primarily meant to debug GObject cycles and leaks that
are not detected.
https://bugzilla.gnome.org/show_bug.cgi?id=679688
-rw-r--r-- | gi/keep-alive.c | 71 |
1 files changed, 70 insertions, 1 deletions
diff --git a/gi/keep-alive.c b/gi/keep-alive.c index d45740a3..afacf14a 100644 --- a/gi/keep-alive.c +++ b/gi/keep-alive.c @@ -165,6 +165,74 @@ keep_alive_trace(JSTracer *tracer, priv->inside_trace = FALSE; } +static char* +jsobj_to_string(JSContext* cx, JSObject *obj) +{ + char* value = NULL; + + if (JS_ObjectIsFunction(cx, obj)) { + JSFunction *fn = JS_ValueToFunction(cx, OBJECT_TO_JSVAL(obj)); + JSString *str; + + str = JS_GetFunctionId(fn); + if (str) { + value = NULL; + gjs_try_string_to_utf8(cx, STRING_TO_JSVAL(str), &value, NULL); + } else { + value = g_strdup ("anonymous function"); + } + } else { + value = g_strdup_printf("[object %s]", JS_GetClass(cx, obj)->name); + } + + if (!value) + value = g_strdup ("[unknown object]"); + return value; +} + +static void +print_foreach(void *key, + void *value, + void *data) +{ + Child *child = value; + JSContext *context = data; + + if (child->child != NULL) { + char *string; + + string = jsobj_to_string(context, child->child); + g_printerr("%p: %s\n", child->child, string); + + g_free(string); + } +} + +static JSBool +print_roots (JSContext *context, + uintN argc, + jsval *vp) +{ + JSObject *obj = JS_THIS_OBJECT(context, vp); + KeepAlive *priv; + + JS_BeginRequest(context); + + priv = priv_from_js(context, obj); + + if (priv == NULL) /* prototype */ + return JS_TRUE; + + g_printerr("**** BEGIN GJS root table dump ****\n"); + g_hash_table_foreach(priv->children, print_foreach, context); + g_printerr("**** END GJS root table dump ****\n"); + + JS_SET_RVAL(context, vp, JSVAL_VOID); + JS_EndRequest(context); + + return JS_TRUE; +} + /* The bizarre thing about this vtable is that it applies to both * instances of the object, and to the prototype that instances of the * class have. @@ -201,7 +269,8 @@ static JSPropertySpec gjs_keep_alive_proto_props[] = { }; static JSFunctionSpec gjs_keep_alive_proto_funcs[] = { - { NULL } + { "print_roots", (JSNative)print_roots, 0, 0 }, + { NULL }, }; JSObject* |