[gjs] Use JS_SetRuntimePrivate() rather than GDataset for runtime data
- From: Owen Taylor <otaylor src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs] Use JS_SetRuntimePrivate() rather than GDataset for runtime data
- Date: Thu, 30 Sep 2010 14:49:38 +0000 (UTC)
commit e979fe2f218232e2f671e4b7af8498ac80a6e100
Author: Owen W. Taylor <otaylor fishsoup net>
Date: Wed Sep 29 18:42:17 2010 -0400
Use JS_SetRuntimePrivate() rather than GDataset for runtime data
GDataset is slow - it requires thread locking and hash table lookups.
Since we don't support foreign JSRuntimes at the moment we can use
JS_SetRuntimePrivate() which will have better performance.
The public API functions gjs_runtime_get/set_data() are removed; if
they were being used outside of GJS the users will have to track their
data themselves.
https://bugzilla.gnome.org/show_bug.cgi?id=630964
gjs/context.c | 20 +++---------
gjs/jsapi-util.c | 86 +++++++++++++++++++++++++++++++++++++----------------
gjs/jsapi-util.h | 9 ++----
3 files changed, 68 insertions(+), 47 deletions(-)
---
diff --git a/gjs/context.c b/gjs/context.c
index 4079f6f..7c0363e 100644
--- a/gjs/context.c
+++ b/gjs/context.c
@@ -354,22 +354,11 @@ gjs_context_dispose(GObject *object)
if (js_context->runtime != NULL) {
if (js_context->we_own_runtime) {
- gjs_debug(GJS_DEBUG_CONTEXT,
- "Destroying JS runtime");
-
- JS_DestroyRuntime(js_context->runtime);
-
- /* finalize the dataset from jsapi-util.c ... for
- * "foreign" runtimes this just never happens for
- * now... we do this after the runtime itself is destroyed
- * because we might have finalizers run by
- * JS_DestroyRuntime() that rely on data we've set on the
- * runtime, such as the dynamic class structs.
+ /* Cleans up data as well as destroying the runtime. Foreign
+ * contexts aren't supported at the moment; if we supported
+ * them, then the data simply would't get cleaned up.
*/
- gjs_debug(GJS_DEBUG_CONTEXT,
- "Destroying any remaining dataset items on runtime");
-
- g_dataset_destroy(js_context->runtime);
+ gjs_runtime_destroy(js_context->runtime);
}
js_context->runtime = NULL;
}
@@ -533,6 +522,7 @@ gjs_context_constructor (GType type,
gjs_fatal("Failed to create javascript runtime");
JS_SetGCParameter(js_context->runtime, JSGC_MAX_BYTES, 0xffffffff);
js_context->we_own_runtime = TRUE;
+ gjs_runtime_init(js_context->runtime);
}
js_context->context = JS_NewContext(js_context->runtime, 8192 /* stack chunk size */);
diff --git a/gjs/jsapi-util.c b/gjs/jsapi-util.c
index 6a3a138..0c55ed6 100644
--- a/gjs/jsapi-util.c
+++ b/gjs/jsapi-util.c
@@ -65,22 +65,6 @@ typedef struct {
static RuntimeData* get_data_from_runtime(JSRuntime *runtime);
static RuntimeData* get_data_from_context(JSContext *context);
-void*
-gjs_runtime_get_data(JSRuntime *runtime,
- const char *name)
-{
- return g_dataset_get_data(runtime, name);
-}
-
-void
-gjs_runtime_set_data(JSRuntime *runtime,
- const char *name,
- void *data,
- GDestroyNotify dnotify)
-{
- g_dataset_set_data_full(runtime, name, data, dnotify);
-}
-
/**
* gjs_get_import_global:
* @context: a #JSContext
@@ -285,13 +269,67 @@ gjs_init_context_standard (JSContext *context)
return TRUE;
}
-static void
-runtime_data_destroy_notify(void *data)
+/**
+ * gjs_runtime_init:
+ * @runtime: a #JSRuntime
+ *
+ * Initializes a #JSRuntime for use with GJS
+ *
+ * This should only be called by GJS, not by applications.
+ */
+void
+gjs_runtime_init(JSRuntime *runtime)
{
- RuntimeData *rd = data;
+ RuntimeData *rd;
+
+ /* If we went back to supporting foreign contexts, we couldn't use
+ * JS_SetRuntimePrivate() because the runtime's owner might
+ * already be using it. A simple solution would be to just store
+ * the runtime data in a global variable - multiple copies of GJS
+ * in the same process at the same time have issues anyways
+ * because of limitations of GObject toggle references - if two
+ * separate entities toggle reference an object it will leak.
+ */
+ if (JS_GetRuntimePrivate(runtime) != NULL)
+ gjs_fatal("JSRuntime already initialized or private data in use by someone else");
+
+ rd = g_slice_new0(RuntimeData);
+ rd->dynamic_classes = g_hash_table_new(g_direct_hash, g_direct_equal);
+ JS_SetRuntimePrivate(runtime, rd);
+}
+
+/**
+ * gjs_runtime_destroy:
+ * @runtime: a #JSRuntime
+ *
+ * Calls JS_DestroyRuntime() on runtime and frees data allocated by
+ * gjs_runtime_init(); these are unified into a single call because we
+ * need to order things so that the allocated data is cleaned up
+ * after JS_DestroyRuntime(). We might have finalizers run by
+ * JS_DestroyRuntime() that rely on the information stored in the data,
+ * such as the dynamic class structs.
+ *
+ * This should only be called by GJS, not by applications.
+ */
+void
+gjs_runtime_destroy(JSRuntime *runtime)
+{
+ RuntimeData *rd;
void *key;
void *value;
+ rd = JS_GetRuntimePrivate(runtime);
+ if (rd->context_stack != NULL || rd->current_frame.depth != 0)
+ gjs_fatal("gjs_runtime_destroy() called during gjs_push_context()");
+
+ gjs_debug(GJS_DEBUG_CONTEXT,
+ "Destroying JS runtime");
+
+ JS_DestroyRuntime(runtime);
+
+ gjs_debug(GJS_DEBUG_CONTEXT,
+ "Destroying any remaining dataset items on runtime");
+
while (gjs_g_hash_table_remove_one(rd->dynamic_classes, &key, &value)) {
JSClass *clasp = value;
@@ -312,13 +350,9 @@ get_data_from_runtime(JSRuntime *runtime)
{
RuntimeData *rd;
- rd = gjs_runtime_get_data(runtime, "gjs-api-util-data");
- if (rd == NULL) {
- rd = g_slice_new0(RuntimeData);
- rd->dynamic_classes = g_hash_table_new(g_direct_hash, g_direct_equal);
- gjs_runtime_set_data(runtime, "gjs-api-util-data",
- rd, runtime_data_destroy_notify);
- }
+ rd = JS_GetRuntimePrivate(runtime);
+ if (G_UNLIKELY(rd == NULL))
+ gjs_fatal("JSRuntime not initialized for use with GJS");
return rd;
}
diff --git a/gjs/jsapi-util.h b/gjs/jsapi-util.h
index f94e010..173c8b7 100644
--- a/gjs/jsapi-util.h
+++ b/gjs/jsapi-util.h
@@ -193,12 +193,9 @@ jsval cname##_create_proto(JSContext *context, JSObject *module, const char *pro
gboolean gjs_init_context_standard (JSContext *context);
-void* gjs_runtime_get_data (JSRuntime *runtime,
- const char *name);
-void gjs_runtime_set_data (JSRuntime *runtime,
- const char *name,
- void *data,
- GDestroyNotify dnotify);
+void gjs_runtime_init (JSRuntime *runtime);
+void gjs_runtime_destroy (JSRuntime *runtime);
+
JSContext* gjs_runtime_get_current_context (JSRuntime *runtime);
void gjs_runtime_set_default_context (JSRuntime *runtime,
JSContext *context);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]