[gjs: 5/6] context: Cleanup completed trampoline in context, as this is what they belong to




commit 713ed60f719e2e11a20fd1508210b2195247d547
Author: Marco Trevisan (TreviƱo) <mail 3v1n0 net>
Date:   Mon May 17 18:17:02 2021 +0200

    context: Cleanup completed trampoline in context, as this is what they belong to
    
    We're currently keeping a list of trampolines in a static vector, this
    is acceptable (at least for a single-context scenario), but trampolines are
    bound to a specific context so better to move the handling in the context.

 gi/function.cpp           | 10 +---------
 gi/function.h             |  2 --
 gjs/context-private.h     |  3 +++
 gjs/context.cpp           | 13 +++++++++++--
 gjs/jsapi-util-root.h     |  2 --
 test/gjs-test-rooting.cpp |  1 +
 6 files changed, 16 insertions(+), 15 deletions(-)
---
diff --git a/gi/function.cpp b/gi/function.cpp
index 672a4464..4c9c649a 100644
--- a/gi/function.cpp
+++ b/gi/function.cpp
@@ -174,12 +174,6 @@ class Function : public CWrapper<Function> {
 
 }  // namespace Gjs
 
-/* Because we can't free the mmap'd data for a callback
- * while it's in use, this list keeps track of ones that
- * will be freed the next time we invoke a C function.
- */
-static std::vector<Gjs::Closure::Ptr> completed_trampolines;
-
 template <typename T, GITypeTag TAG = GI_TYPE_TAG_VOID>
 static inline std::enable_if_t<std::is_integral_v<T> && std::is_signed_v<T>>
 set_ffi_arg(void* result, GIArgument* value) {
@@ -339,7 +333,7 @@ void GjsCallbackTrampoline::callback_closure(GIArgument** args, void* result) {
                 // that has been set in gjs_marshal_callback_in()
                 gjs_debug_closure("Saving async closure for gc cleanup %p",
                                   trampoline);
-                completed_trampolines.emplace_back(trampoline);
+                gjs->async_closure_enqueue_for_gc(trampoline);
             }
             gjs->schedule_gc_if_needed();
         }
@@ -740,8 +734,6 @@ std::string Gjs::Function::format_name() {
     return retval;
 }
 
-void gjs_function_clear_async_closures() { completed_trampolines.clear(); }
-
 namespace Gjs {
 
 static void* get_return_ffi_pointer_from_giargument(
diff --git a/gi/function.h b/gi/function.h
index 61868238..498b5481 100644
--- a/gi/function.h
+++ b/gi/function.h
@@ -157,6 +157,4 @@ bool gjs_invoke_constructor_from_c(JSContext* cx, GIFunctionInfo* info,
                                    const JS::CallArgs& args,
                                    GIArgument* rvalue);
 
-void gjs_function_clear_async_closures();
-
 #endif  // GI_FUNCTION_H_
diff --git a/gjs/context-private.h b/gjs/context-private.h
index b472ef4f..e29b495c 100644
--- a/gjs/context-private.h
+++ b/gjs/context-private.h
@@ -32,6 +32,7 @@
 #include <jsapi.h>        // for JS_GetContextPrivate
 #include <jsfriendapi.h>  // for ScriptEnvironmentPreparer
 
+#include "gi/closure.h"
 #include "gjs/context.h"
 #include "gjs/jsapi-util.h"
 #include "gjs/macros.h"
@@ -80,6 +81,7 @@ class GjsContextPrivate : public JS::JobQueue {
     unsigned m_idle_drain_handler;
 
     std::vector<std::pair<DestroyNotify, void*>> m_destroy_notifications;
+    std::vector<Gjs::Closure::Ptr> m_async_closures;
     std::unordered_map<uint64_t, GjsAutoChar> m_unhandled_rejection_stacks;
 
     GjsProfiler* m_profiler;
@@ -246,6 +248,7 @@ class GjsContextPrivate : public JS::JobQueue {
 
     void register_notifier(DestroyNotify notify_func, void* data);
     void unregister_notifier(DestroyNotify notify_func, void* data);
+    void async_closure_enqueue_for_gc(Gjs::Closure*);
 
     [[nodiscard]] bool register_module(const char* identifier,
                                        const char* filename, GError** error);
diff --git a/gjs/context.cpp b/gjs/context.cpp
index e5a01fcf..10a80a0c 100644
--- a/gjs/context.cpp
+++ b/gjs/context.cpp
@@ -61,7 +61,6 @@
 #include <mozilla/UniquePtr.h>
 
 #include "gi/closure.h"  // for Closure::Ptr, Closure
-#include "gi/function.h"
 #include "gi/object.h"
 #include "gi/private.h"
 #include "gi/repo.h"
@@ -794,7 +793,9 @@ void GjsContextPrivate::on_garbage_collection(JSGCStatus status, JS::GCReason re
             // order to minimize the chances of objects having a pending toggle
             // up queued when they are garbage collected.
             gjs_object_clear_toggles();
-            gjs_function_clear_async_closures();
+
+            m_async_closures.clear();
+            m_async_closures.shrink_to_fit();
             break;
         case JSGC_END:
             if (m_profiler && m_gc_begin_time != 0) {
@@ -1089,6 +1090,14 @@ void GjsContextPrivate::unregister_unhandled_promise_rejection(uint64_t id) {
               "previously marked as unhandled", erased == 1));
 }
 
+void GjsContextPrivate::async_closure_enqueue_for_gc(Gjs::Closure* trampoline) {
+    //  Because we can't free the mmap'd data for a callback
+    //  while it's in use, this list keeps track of ones that
+    //  will be freed the next time gc happens
+    g_assert(!trampoline->context() || trampoline->context() == m_cx);
+    m_async_closures.emplace_back(trampoline);
+}
+
 /**
  * gjs_context_maybe_gc:
  * @context: a #GjsContext
diff --git a/gjs/jsapi-util-root.h b/gjs/jsapi-util-root.h
index bc58ba36..6758c722 100644
--- a/gjs/jsapi-util-root.h
+++ b/gjs/jsapi-util-root.h
@@ -21,8 +21,6 @@
 #include <js/TracingAPI.h>
 #include <js/TypeDecls.h>
 
-#include "gjs/context-private.h"
-#include "gjs/context.h"
 #include "gjs/macros.h"
 #include "util/log.h"
 
diff --git a/test/gjs-test-rooting.cpp b/test/gjs-test-rooting.cpp
index c3c89eb3..a58753da 100644
--- a/test/gjs-test-rooting.cpp
+++ b/test/gjs-test-rooting.cpp
@@ -12,6 +12,7 @@
 #include <js/Value.h>
 #include <jsapi.h>  // for JS_GetPrivate, JS_NewObject, JS_Set...
 
+#include "gjs/context-private.h"
 #include "gjs/jsapi-util-root.h"
 #include "test/gjs-test-utils.h"
 


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