[gjs/wip/ptomato/785657: 2/2] closure: Prevent collection of callable when invalidating



commit 1ebfaf6d762f7d6db02e6d67a9f408e54ee03881
Author: Philip Chimento <philip chimento gmail com>
Date:   Tue Aug 22 21:47:57 2017 -0700

    closure: Prevent collection of callable when invalidating
    
    When invalidating a closure, make sure to prevent the callable object
    from being collected in the current GC pass. JS::ExposeObjectToActiveJS()
    will make sure it is not marked for GC. This is so that the graph of
    reachable nodes does not change during a GC run.

 gi/closure.cpp        |    1 +
 gjs/jsapi-util-root.h |   20 ++++++++++++++++++++
 2 files changed, 21 insertions(+), 0 deletions(-)
---
diff --git a/gi/closure.cpp b/gi/closure.cpp
index 1440b4a..5c03926 100644
--- a/gi/closure.cpp
+++ b/gi/closure.cpp
@@ -174,6 +174,7 @@ closure_set_invalid(gpointer  data,
     } else {
         gjs_debug_closure("Invalidating signal closure %p which calls object "
                           "%p", closure, self->obj.get());
+        self->obj.prevent_collection();
         self->obj.reset();
     }
 
diff --git a/gjs/jsapi-util-root.h b/gjs/jsapi-util-root.h
index 33f748d..f192c12 100644
--- a/gjs/jsapi-util-root.h
+++ b/gjs/jsapi-util-root.h
@@ -67,6 +67,7 @@
 template<typename T>
 struct GjsHeapOperation {
     static bool update_after_gc(JS::Heap<T> *location);
+    static void expose_to_js(JS::Heap<T>& thing);
 };
 
 template<>
@@ -77,6 +78,14 @@ struct GjsHeapOperation<JSObject *> {
         JS_UpdateWeakPointerAfterGC(location);
         return (location->unbarrieredGet() == nullptr);
     }
+
+    static void
+    expose_to_js(JS::Heap<JSObject *>& thing) {
+        JSObject *obj = thing.unbarrieredGet();
+        /* If the object has been swept already, then the zone is nullptr */
+        if (obj && js::gc::detail::GetGCThingZone(uintptr_t(obj)))
+            JS::ExposeObjectToActiveJS(obj);
+    }
 };
 
 template<>
@@ -249,6 +258,17 @@ public:
         m_heap = thing;
     }
 
+    /* Marks an object as reachable for one GC with ExposeObjectToActiveJS().
+     * Use to avoid stopping tracing an object during GC. This makes no sense
+     * in the rooted case. */
+    void
+    prevent_collection(void)
+    {
+        debug("prevent_collection()");
+        g_assert(!m_rooted);
+        GjsHeapOperation<T>::expose_to_js(m_heap);
+    }
+
     void
     reset(void)
     {


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