[gjs/wip/ptomato/mozjs38: 4/28] function: Two wrappers in GjsCallbackTrampoline
- From: Philip Chimento <pchimento src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs/wip/ptomato/mozjs38: 4/28] function: Two wrappers in GjsCallbackTrampoline
- Date: Wed, 25 Jan 2017 02:35:21 +0000 (UTC)
commit dec13d55264e912e127e94b17e049e24b7e44bfe
Author: Philip Chimento <philip chimento gmail com>
Date: Wed Jan 11 23:34:40 2017 -0800
function: Two wrappers in GjsCallbackTrampoline
The previous situation was that the JS::Value holding the a trampoline's
function was stored in a JS::Heap wrapper. If the function was owned by
the trampoline (the normal case), then it was rooted. If the function was
a vfunc, in which case it was owned by the GObject class prototype and
the trampoline was essentially leaked, then it remained a weak pointer.
In SpiderMonkey 38, JS::AddValueRoot() and friends are going away, in
favour of JS::PersistentRooted. However, JS::PersistentRooted does not
have the option of maintaining a weak pointer to the value. Therefore, we
use a JS::Heap to store a vfunc value and JS::PersistentRooted* otherwise.
We maintain the invariant that one of the two must be null and provide a
function to get the function value from the appropriate wrapper.
This will still need to change further, since weak pointers must be
updated when they are moved by the GC.
https://bugzilla.gnome.org/show_bug.cgi?id=776966
gi/function.cpp | 34 +++++++++++++++++++++-------------
gi/function.h | 5 +++++
2 files changed, 26 insertions(+), 13 deletions(-)
---
diff --git a/gi/function.cpp b/gi/function.cpp
index dc14281..403c788 100644
--- a/gi/function.cpp
+++ b/gi/function.cpp
@@ -82,14 +82,7 @@ gjs_callback_trampoline_unref(GjsCallbackTrampoline *trampoline)
trampoline->ref_count--;
if (trampoline->ref_count == 0) {
- JSContext *context = trampoline->context;
-
- if (!trampoline->is_vfunc) {
- JS_BeginRequest(context);
- JS::RemoveValueRoot(context, &trampoline->js_function);
- JS_EndRequest(context);
- }
-
+ delete trampoline->js_rooted_function;
g_callable_info_free_closure(trampoline->info, trampoline->closure);
g_base_info_unref( (GIBaseInfo*) trampoline->info);
g_free (trampoline->param_types);
@@ -98,6 +91,18 @@ gjs_callback_trampoline_unref(GjsCallbackTrampoline *trampoline)
}
}
+static JS::Value
+gjs_callback_trampoline_get_function(GjsCallbackTrampoline *trampoline)
+{
+ g_assert(trampoline->js_function.isUndefined() ||
+ trampoline->js_rooted_function == NULL);
+
+ if (trampoline->is_vfunc)
+ return trampoline->js_function;
+ else
+ return trampoline->js_rooted_function->get();
+}
+
static void
set_return_ffi_arg_from_giargument (GITypeInfo *ret_type,
void *result,
@@ -208,7 +213,7 @@ gjs_callback_closure(ffi_cif *cif,
}
JS_BeginRequest(context);
- func_obj = &trampoline->js_function.toObject();
+ func_obj = &gjs_callback_trampoline_get_function(trampoline).toObject();
JSAutoCompartment ac(context, func_obj);
n_args = g_callable_info_get_n_args(trampoline->info);
@@ -219,7 +224,8 @@ gjs_callback_closure(ffi_cif *cif,
JS::AutoValueVector jsargs(context);
jsargs.reserve(n_args);
JS::RootedValue rval(context);
- JS::RootedValue rooted_function(context, trampoline->js_function);
+ JS::RootedValue rooted_function(context,
+ gjs_callback_trampoline_get_function(trampoline));
JS::RootedObject this_object(context);
for (i = 0, n_jsargs = 0; i < n_args; i++) {
@@ -455,9 +461,11 @@ gjs_callback_trampoline_new(JSContext *context,
trampoline->context = context;
trampoline->info = callable_info;
g_base_info_ref((GIBaseInfo*)trampoline->info);
- trampoline->js_function = function;
- if (!is_vfunc)
- JS::AddValueRoot(context, &trampoline->js_function);
+ if (is_vfunc)
+ trampoline->js_function = function;
+ else
+ trampoline->js_rooted_function =
+ new JS::PersistentRootedValue(context, function);
/* Analyze param types and directions, similarly to init_cached_function_data */
n_args = g_callable_info_get_n_args(trampoline->info);
diff --git a/gi/function.h b/gi/function.h
index 8bc9cb1..046abbd 100644
--- a/gi/function.h
+++ b/gi/function.h
@@ -45,7 +45,12 @@ struct GjsCallbackTrampoline {
gint ref_count;
JSContext *context;
GICallableInfo *info;
+
+ /* One of these two must be null, depending on whether the function
+ * is owned by the trampoline (normal) or not (vfunc) */
JS::Heap<JS::Value> js_function;
+ JS::PersistentRootedValue *js_rooted_function;
+
ffi_cif cif;
ffi_closure *closure;
GIScopeType scope;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]