[gjs] Remove support for multiple contexts within a runtime
- From: Jasper St. Pierre <jstpierre src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs] Remove support for multiple contexts within a runtime
- Date: Mon, 7 Jan 2013 18:36:11 +0000 (UTC)
commit 244f1864d2d0a9ab20afa7d793f26843a6cf22e4
Author: Jasper St. Pierre <jstpierre mecheye net>
Date: Thu Jan 3 23:23:50 2013 -0500
Remove support for multiple contexts within a runtime
Remove code and support code to allow for multiple contexts, and
simply store one context. In a thread-safe world, we'd put each
context in thread-local storage, but gjs is not thread-safe, nor
do we expect it will be in the future.
https://bugzilla.gnome.org/show_bug.cgi?id=691109
gi/closure.c | 2 +-
gi/function.c | 8 +--
gi/object.c | 2 +-
gi/value.c | 2 +-
gjs/context.c | 13 +----
gjs/jsapi-util.c | 168 ++++------------------------------------------------
gjs/jsapi-util.h | 11 +---
modules/mainloop.c | 4 +-
8 files changed, 22 insertions(+), 188 deletions(-)
---
diff --git a/gi/closure.c b/gi/closure.c
index 96a7477..1d51aea 100644
--- a/gi/closure.c
+++ b/gi/closure.c
@@ -266,7 +266,7 @@ gjs_closure_invoke(GClosure *closure,
return;
}
- context = gjs_runtime_get_current_context(c->runtime);
+ context = gjs_runtime_get_context(c->runtime);
JS_BeginRequest(context);
if (JS_IsExceptionPending(context)) {
diff --git a/gi/function.c b/gi/function.c
index 1a2c190..a37fb85 100644
--- a/gi/function.c
+++ b/gi/function.c
@@ -80,7 +80,7 @@ gjs_callback_trampoline_unref(GjsCallbackTrampoline *trampoline)
if (trampoline->ref_count == 0) {
JSContext *context;
- context = gjs_runtime_get_current_context(trampoline->runtime);
+ context = gjs_runtime_get_context(trampoline->runtime);
if (!trampoline->is_vfunc) {
JS_BeginRequest(context);
@@ -180,7 +180,7 @@ gjs_callback_closure(ffi_cif *cif,
g_assert(trampoline);
gjs_callback_trampoline_ref(trampoline);
- context = gjs_runtime_get_current_context(trampoline->runtime);
+ context = gjs_runtime_get_context(trampoline->runtime);
JS_BeginRequest(context);
n_args = g_callable_info_get_n_args(trampoline->info);
@@ -878,8 +878,6 @@ gjs_invoke_c_function(JSContext *context,
* separately */
}
- gjs_runtime_push_context(JS_GetRuntime(context), context);
-
g_assert_cmpuint(c_arg_pos, ==, c_argc);
g_assert_cmpuint(gi_arg_pos, ==, gi_argc);
@@ -894,8 +892,6 @@ gjs_invoke_c_function(JSContext *context,
return_value_p = &return_value.v_long;
ffi_call(&(function->invoker.cif), function->invoker.native_address, return_value_p, ffi_arg_pointers);
- gjs_runtime_pop_context(JS_GetRuntime(context));
-
/* Return value and out arguments are valid only if invocation doesn't
* return error. In arguments need to be released always.
*/
diff --git a/gi/object.c b/gi/object.c
index 3e909c7..91841d9 100644
--- a/gi/object.c
+++ b/gi/object.c
@@ -783,7 +783,7 @@ wrapped_gobj_toggle_notify(gpointer data,
* Or if !is_last_ref, we do not want to convert to a strong
* ref since we want everything collected on runtime destroy.
*/
- context = gjs_runtime_get_current_context(runtime);
+ context = gjs_runtime_get_context(runtime);
if (!context)
return;
diff --git a/gi/value.c b/gi/value.c
index 0119d90..909742d 100644
--- a/gi/value.c
+++ b/gi/value.c
@@ -73,7 +73,7 @@ closure_marshal(GClosure *closure,
}
runtime = gjs_closure_get_runtime(closure);
- context = gjs_runtime_get_current_context(runtime);
+ context = gjs_runtime_get_context(runtime);
JS_BeginRequest(context);
argc = n_param_values;
diff --git a/gjs/context.c b/gjs/context.c
index efec0d2..68643dd 100644
--- a/gjs/context.c
+++ b/gjs/context.c
@@ -368,7 +368,6 @@ gjs_context_dispose(GObject *object)
gjs_debug(GJS_DEBUG_CONTEXT,
"Destroying JS context");
- gjs_runtime_set_default_context(js_context->runtime, NULL);
JS_DestroyContext(js_context->context);
js_context->context = NULL;
}
@@ -545,12 +544,13 @@ gjs_context_constructor (GType type,
if (js_context->runtime == NULL)
gjs_fatal("Failed to create javascript runtime");
JS_SetGCParameter(js_context->runtime, JSGC_MAX_BYTES, 0xffffffff);
- gjs_runtime_init(js_context->runtime);
js_context->context = JS_NewContext(js_context->runtime, 8192 /* stack chunk size */);
if (js_context->context == NULL)
gjs_fatal("Failed to create javascript context");
+ gjs_runtime_init(js_context->runtime, js_context->context);
+
JS_BeginRequest(js_context->context);
@@ -630,13 +630,6 @@ gjs_context_constructor (GType type,
4, GJS_MODULE_PROP_FLAGS))
gjs_fatal("Failed to define printerr function");
- /* We need to know what the default context is, since it's the context whose
- * global object is used to load imported JS modules. We currently say that
- * it's the context of the runtime's owner, but if we needed to support
- * externally created runtimes, we could define it in some other fashion.
- */
- gjs_runtime_set_default_context(js_context->runtime, js_context->context);
-
/* We create the global-to-runtime root importer with the
* passed-in search path. If someone else already created
* the root importer, this is a no-op.
@@ -983,7 +976,6 @@ gjs_context_eval(GjsContext *js_context,
/* JS_EvaluateScript requires a request even though it sort of seems like
* it means we're always in a request?
*/
- gjs_runtime_push_context(js_context->runtime, js_context->context);
JS_BeginRequest(js_context->context);
retval = JSVAL_VOID;
@@ -1051,7 +1043,6 @@ gjs_context_eval(GjsContext *js_context,
}
JS_EndRequest(js_context->context);
- gjs_runtime_pop_context(js_context->runtime);
g_object_unref(G_OBJECT(js_context));
diff --git a/gjs/jsapi-util.c b/gjs/jsapi-util.c
index 3198ec7..61b07ac 100644
--- a/gjs/jsapi-util.c
+++ b/gjs/jsapi-util.c
@@ -43,17 +43,6 @@ gjs_util_error_quark (void)
typedef struct {
JSContext *context;
- int depth;
-} ContextFrame;
-
-typedef struct {
- JSObject *import_global;
-
- JSContext *default_context;
-
- /* In a thread-safe future we'd keep this in per-thread data */
- ContextFrame current_frame;
- GSList *context_stack;
} RuntimeData;
static RuntimeData* get_data_from_runtime(JSRuntime *runtime);
@@ -63,7 +52,7 @@ static RuntimeData* get_data_from_runtime(JSRuntime *runtime);
* @context: a #JSContext
*
* Gets the "import global" for the context's runtime. The import
- * global object is the global object for the default context. It is used
+ * global object is the global object for the context. It is used
* as the root object for the scope of modules loaded by GJS in this
* runtime, and should also be used as the globals 'obj' argument passed
* to JS_InitClass() and the parent argument passed to JS_ConstructObject()
@@ -80,151 +69,24 @@ static RuntimeData* get_data_from_runtime(JSRuntime *runtime);
JSObject*
gjs_get_import_global(JSContext *context)
{
- JSRuntime *runtime = JS_GetRuntime(context);
- RuntimeData *rd;
-
- rd = get_data_from_runtime(runtime);
-
- return rd->import_global;
+ return JS_GetGlobalObject(context);
}
/**
- * gjs_runtime_push_context:
+ * gjs_runtime_get_context:
* @runtime: a #JSRuntime
- * @context: a #JSRuntime
- *
- * Make @context the currently active context for @runtime.
- * A stack is maintained, although switching between different contexts
- * in a nested fashion in the same thread ecan trigger misbehavior in
- * Spidermonkey, so is not recommended. This does not call JS_BeginRequest();
- * the caller needs to do it themselves.
*
- * Should be called when calling from Javascript into native code that
- * could result in callbacks back to Javascript. The context stack allows
- * the callbacks to find the right context to use via gjs_get_current_context().
- *
- * When GJS is made threadsafe, this needs to maintain a per-thread stack
- * rather than a global stack.
- */
-void
-gjs_runtime_push_context(JSRuntime *runtime,
- JSContext *context)
-{
- RuntimeData *rd;
-
- rd = get_data_from_runtime(runtime);
-
- if (context == rd->current_frame.context) {
- rd->current_frame.depth++;
- } else {
- rd->context_stack = g_slist_prepend(rd->context_stack,
- g_slice_dup(ContextFrame, &rd->current_frame));
- rd->current_frame.context = context;
- rd->current_frame.depth = 0;
- }
-}
-
-/**
- * gjs_runtime_pop_context:
- * @runtime: a #JSRuntime
+ * Gets the context associated with this runtime.
*
- * Pops a context pushed onto the stack of active contexts by
- * gjs_runtime_push_context().
- */
-void
-gjs_runtime_pop_context(JSRuntime *runtime)
-{
- RuntimeData *rd;
-
- rd = get_data_from_runtime(runtime);
-
- if (rd->current_frame.depth == 0) {
- if (rd->context_stack == NULL)
- gjs_fatal("gjs_runtime_pop_context() called more times than gjs_runtime_push_context()");
-
- rd->current_frame = *(ContextFrame *)rd->context_stack->data;
- g_slice_free(ContextFrame, rd->context_stack->data);
- rd->context_stack = g_slist_delete_link(rd->context_stack, rd->context_stack);
- } else {
- rd->current_frame.depth--;
- }
-}
-
-/**
- * gjs_runtime_set_default_context:
- * @runtime: a #JSRuntime
- * @context: a #JSContext
- *
- * Makes @context the default context for @runtime. The default context is the
- * context used for executing callbacks when no other context is active.
- * This generally should only be called by GJS - GJS sets the default context
- * when #GjsContext creates a runtime, and subsequent calls to this function
- * will produce an error.
- */
-void
-gjs_runtime_set_default_context(JSRuntime *runtime,
- JSContext *context)
-{
- RuntimeData *rd;
-
- rd = get_data_from_runtime(runtime);
-
- if (rd->context_stack != NULL || rd->current_frame.depth != 0)
- gjs_fatal("gjs_runtime_set_default_context() called during gjs_push_context()");
-
- if (context != NULL) {
- if (rd->default_context != NULL)
- gjs_fatal("gjs_runtime_set_default_context() called twice on the same JSRuntime");
- rd->default_context = context;
- rd->current_frame.context = context;
- rd->import_global = JS_GetGlobalObject(rd->default_context);
- } else {
- rd->default_context = NULL;
- rd->current_frame.context = NULL;
- rd->import_global = NULL;
- }
-}
-
-/**
- * gjs_runtime_get_default_context:
- * @runtime: a #JSRuntime
- *
- * Gets the default context for @runtime. Generally you should use
- * gjs_runtime_get_current_context() instead.
- *
- * Return value: the default context, or %NULL if GJS hasn't been initialized
- * for the runtime or is being shut down.
+ * Return value: the context, or %NULL if GJS hasn't been initialized
+ * for the runtime or is being shut down.
*/
JSContext *
-gjs_runtime_get_default_context(JSRuntime *runtime)
+gjs_runtime_get_context(JSRuntime *runtime)
{
RuntimeData *rd;
-
rd = get_data_from_runtime(runtime);
-
- return rd->default_context;
-}
-
-/**
- * gjs_runtime_get_current_context:
- * @runtime: a #JSRuntime
- *
- * Gets the right context to use for code that doesn't already have a JSContext
- * passed to it, like a callback from native code. If a context is currently
- * active (see gjs_push_context()), uses that, otherwise uses the default
- * context for the runtime.
- *
- * Return value: the current context, or %NULL if GJS hasn't been initialized
- * for the runtime or is being shut down.
- */
-JSContext *
-gjs_runtime_get_current_context(JSRuntime *runtime)
-{
- RuntimeData *rd;
-
- rd = get_data_from_runtime(runtime);
-
- return rd->current_frame.context;
+ return rd->context;
}
static JSClass global_class = {
@@ -264,22 +126,16 @@ gjs_init_context_standard (JSContext *context)
* This should only be called by GJS, not by applications.
*/
void
-gjs_runtime_init(JSRuntime *runtime)
+gjs_runtime_init(JSRuntime *runtime,
+ JSContext *context)
{
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->context = context;
JS_SetRuntimePrivate(runtime, rd);
}
@@ -302,8 +158,6 @@ gjs_runtime_destroy(JSRuntime *runtime)
RuntimeData *rd;
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");
diff --git a/gjs/jsapi-util.h b/gjs/jsapi-util.h
index 3c14c5c..e825b5f 100644
--- a/gjs/jsapi-util.h
+++ b/gjs/jsapi-util.h
@@ -181,16 +181,11 @@ jsval gjs_##cname##_create_proto(JSContext *context, JSObject *module, const cha
gboolean gjs_init_context_standard (JSContext *context);
-void gjs_runtime_init (JSRuntime *runtime);
+void gjs_runtime_init (JSRuntime *runtime,
+ JSContext *context);
void gjs_runtime_destroy (JSRuntime *runtime);
-JSContext* gjs_runtime_get_current_context (JSRuntime *runtime);
-void gjs_runtime_set_default_context (JSRuntime *runtime,
- JSContext *context);
-JSContext* gjs_runtime_get_default_context (JSRuntime *runtime);
-void gjs_runtime_push_context (JSRuntime *runtime,
- JSContext *context);
-void gjs_runtime_pop_context (JSRuntime *runtime);
+JSContext* gjs_runtime_get_context (JSRuntime *runtime);
JSObject* gjs_get_import_global (JSContext *context);
gboolean gjs_object_has_property (JSContext *context,
JSObject *obj,
diff --git a/modules/mainloop.c b/modules/mainloop.c
index 015740a..cbf4069 100644
--- a/modules/mainloop.c
+++ b/modules/mainloop.c
@@ -101,9 +101,7 @@ gjs_main_loop_run(JSContext *context,
context);
g_free(cancel_id);
- gjs_runtime_push_context(JS_GetRuntime(context), context);
g_main_loop_run(main_loop);
- gjs_runtime_pop_context(JS_GetRuntime(context));
g_main_loop_unref(main_loop);
return JS_TRUE;
@@ -124,7 +122,7 @@ closure_source_func(void *data)
return FALSE;
runtime = gjs_closure_get_runtime(closure);
- context = gjs_runtime_get_current_context(runtime);
+ context = gjs_runtime_get_context(runtime);
JS_BeginRequest(context);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]