[gjs] object: Trace vfunc trampolines



commit a8717963f7a8775246e34461c74dc0b187caf91c
Author: Philip Chimento <philip endlessm com>
Date:   Mon Feb 6 17:35:35 2017 -0800

    object: Trace vfunc trampolines
    
    Previously these trampolines were leaked, and the JS functions they
    pointed to were treated as weak pointers. We still have to leak the
    trampoline structs themselves, because the GType's vtable still refers to
    them.
    
    However, we can tie the JS functions to the lifetime of the prototype
    and trace them during garbage collection, which will become required in
    SpiderMonkey 38 when they can be moved around during GC.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=776966

 gi/object.cpp         |   14 ++++++++++++++
 gjs/jsapi-util-root.h |   11 +++++++++++
 2 files changed, 25 insertions(+), 0 deletions(-)
---
diff --git a/gi/object.cpp b/gi/object.cpp
index fd4aeb2..6142972 100644
--- a/gi/object.cpp
+++ b/gi/object.cpp
@@ -23,6 +23,7 @@
 
 #include <config.h>
 
+#include <deque>
 #include <memory>
 #include <set>
 #include <stack>
@@ -65,6 +66,9 @@ struct ObjectInstance {
        prototypes) */
     GTypeClass *klass;
 
+    /* A list of all vfunc trampolines, used when tracing */
+    std::deque<GjsCallbackTrampoline *> vfuncs;
+
     unsigned js_object_finalized : 1;
 };
 
@@ -1524,6 +1528,9 @@ object_instance_trace(JSTracer *tracer,
 
         gjs_closure_trace(cd->closure, tracer);
     }
+
+    for (auto vfunc : priv->vfuncs)
+        vfunc->js_function.trace(tracer, "ObjectInstance::vfunc");
 }
 
 static void
@@ -1569,6 +1576,12 @@ object_instance_finalize(JSFreeOp  *fop,
         release_native_object(priv);
     }
 
+    /* We have to leak the trampolines, since the GType's vtable still refers
+     * to them */
+    for (auto iter : priv->vfuncs)
+        iter->js_function.reset();
+    priv->vfuncs.clear();
+
     if (priv->keep_alive.rooted()) {
         /* This happens when the refcount on the object is still >1,
          * for example with global objects GDK never frees like GdkDisplay,
@@ -2438,6 +2451,7 @@ gjs_hook_up_vfunc(JSContext *cx,
                                                  GI_SCOPE_TYPE_NOTIFIED, true);
 
         *((ffi_closure **)method_ptr) = trampoline->closure;
+        priv->vfuncs.push_back(trampoline);
 
         g_base_info_unref(interface_info);
         g_base_info_unref(type_info);
diff --git a/gjs/jsapi-util-root.h b/gjs/jsapi-util-root.h
index 4143e98..c80d123 100644
--- a/gjs/jsapi-util-root.h
+++ b/gjs/jsapi-util-root.h
@@ -90,6 +90,17 @@ struct GjsHeapOperation<JSObject *> {
     }
 };
 
+template<>
+struct GjsHeapOperation<JS::Value> {
+    static void
+    trace(JSTracer            *tracer,
+          JS::Heap<JS::Value> *thing,
+          const char          *name)
+    {
+        JS_CallHeapValueTracer(tracer, thing, name);
+    }
+};
+
 /* GjsMaybeOwned is intended only for use in heap allocation. Do not allocate it
  * on the stack, and do not allocate any instances of structures that have it as
  * a member on the stack either. Unfortunately we cannot enforce this at compile


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]