summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Walters <walters@verbum.org>2011-09-15 19:33:23 -0400
committerColin Walters <walters@verbum.org>2011-09-16 16:57:42 -0400
commit20cfbeb9744a8d44b8e9dcce23d0c8e0f26842a1 (patch)
tree62c89c5840bfea044bdc848174f19018b8609010
parent74a21aeb659bfbb9e7354b41d1a72efcfb60cfb6 (diff)
downloadgjs-20cfbeb9744a8d44b8e9dcce23d0c8e0f26842a1.tar.gz
context: Add optional signal emitted after a GC finishes
Embedders may want to perform garbage collection profiling; support this with an optional signal emitted after a collection finishes. I added a boolean to avoid calling JS_SetGCCallback() if not used, because there's no way for that API to chain. https://bugzilla.gnome.org/show_bug.cgi?id=659253
-rw-r--r--gjs/context.c70
1 files changed, 65 insertions, 5 deletions
diff --git a/gjs/context.c b/gjs/context.c
index d931a3b5..5688477f 100644
--- a/gjs/context.c
+++ b/gjs/context.c
@@ -56,6 +56,8 @@ static void gjs_context_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec);
+static JSBool gjs_on_context_gc (JSContext *cx,
+ JSGCStatus status);
struct _GjsContext {
GObject parent;
@@ -70,7 +72,10 @@ struct _GjsContext {
char **search_path;
- unsigned int we_own_runtime : 1;
+ guint idle_emit_gc_id;
+
+ guint we_own_runtime : 1;
+ guint gc_notifications_enabled : 1;
};
struct _GjsContextClass {
@@ -79,19 +84,19 @@ struct _GjsContextClass {
G_DEFINE_TYPE(GjsContext, gjs_context, G_TYPE_OBJECT);
-#if 0
enum {
+ SIGNAL_GC,
LAST_SIGNAL
};
static int signals[LAST_SIGNAL];
-#endif
enum {
PROP_0,
PROP_JS_VERSION,
PROP_SEARCH_PATH,
- PROP_RUNTIME
+ PROP_RUNTIME,
+ PROP_GC_NOTIFICATIONS
};
@@ -335,6 +340,22 @@ gjs_context_class_init(GjsContextClass *klass)
PROP_JS_VERSION,
pspec);
+ pspec = g_param_spec_boolean("gc-notifications",
+ "",
+ "Whether or not to emit the \"gc\" signal",
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+
+ g_object_class_install_property(object_class,
+ PROP_GC_NOTIFICATIONS,
+ pspec);
+
+ signals[SIGNAL_GC] = g_signal_new("gc", G_TYPE_FROM_CLASS(klass),
+ G_SIGNAL_RUN_LAST, 0,
+ NULL, NULL,
+ NULL,
+ G_TYPE_NONE, 0);
+
gjs_register_native_module("byteArray", gjs_define_byte_array_stuff, 0);
}
@@ -386,6 +407,11 @@ gjs_context_finalize(GObject *object)
js_context = GJS_CONTEXT(object);
+ if (js_context->idle_emit_gc_id > 0) {
+ g_source_remove (js_context->idle_emit_gc_id);
+ js_context->idle_emit_gc_id = 0;
+ }
+
if (js_context->search_path != NULL) {
g_strfreev(js_context->search_path);
js_context->search_path = NULL;
@@ -674,6 +700,9 @@ gjs_context_constructor (GType type,
/* For GjsDBus */
g_irepository_prepend_search_path(PKGLIBDIR);
+ if (js_context->gc_notifications_enabled)
+ JS_SetGCCallback(js_context->context, gjs_on_context_gc);
+
JS_EndRequest(js_context->context);
g_static_mutex_lock (&contexts_lock);
@@ -697,6 +726,9 @@ gjs_context_get_property (GObject *object,
case PROP_JS_VERSION:
g_value_set_string(value, js_context->jsversion_string);
break;
+ case PROP_GC_NOTIFICATIONS:
+ g_value_set_boolean(value, js_context->gc_notifications_enabled);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -727,7 +759,9 @@ gjs_context_set_property (GObject *object,
else
js_context->jsversion_string = g_value_dup_string(value);
break;
-
+ case PROP_GC_NOTIFICATIONS:
+ js_context->gc_notifications_enabled = g_value_get_boolean(value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -865,6 +899,32 @@ gjs_context_maybe_gc (GjsContext *context)
gjs_maybe_gc(context->context);
}
+static gboolean
+gjs_context_idle_emit_gc (gpointer data)
+{
+ GjsContext *gjs_context = data;
+
+ gjs_context->idle_emit_gc_id = 0;
+
+ g_signal_emit (gjs_context, signals[SIGNAL_GC], 0);
+
+ return FALSE;
+}
+
+static JSBool
+gjs_on_context_gc (JSContext *cx,
+ JSGCStatus status)
+{
+ GjsContext *gjs_context = JS_GetContextPrivate(cx);
+
+ if (status == JSGC_END) {
+ if (gjs_context->idle_emit_gc_id == 0)
+ gjs_context->idle_emit_gc_id = g_idle_add (gjs_context_idle_emit_gc, gjs_context);
+ }
+
+ return TRUE;
+}
+
/**
* gjs_context_get_all:
*