[gjs/wip/ptomato/mozjs38: 8/28] object: Trace vfunc trampolines



commit f198b8f6245239882c37668a60faea1adb24d1a7
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 9f63923..8bd4454 100644
--- a/gi/object.cpp
+++ b/gi/object.cpp
@@ -23,6 +23,7 @@
 
 #include <config.h>
 
+#include <deque>
 #include <memory>
 #include <stack>
 #include <string.h>
@@ -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;
 };
 
@@ -1514,6 +1518,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
@@ -1559,6 +1566,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,
@@ -2430,6 +2443,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 7a8e5cc..dfa3226 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]