Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-15:Update
gjs
gjs-aggressive-gc.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File gjs-aggressive-gc.patch of Package gjs
diff --git a/gi/object.cpp b/gi/object.cpp index e77de88..57816d9 100644 --- a/gi/object.cpp +++ b/gi/object.cpp @@ -1010,9 +1010,31 @@ handle_toggle_down(GObject *gobj) * collected by the GC */ if (priv->keep_alive.rooted()) { + GjsContext *context; + gjs_debug_lifecycle(GJS_DEBUG_GOBJECT, "Removing object from keep alive"); priv->keep_alive.switch_to_unrooted(); dissociate_list_remove(priv); + + /* During a GC, the collector asks each object which other + * objects that it wants to hold on to so if there's an entire + * section of the heap graph that's not connected to anything + * else, and not reachable from the root set, then it can be + * trashed all at once. + * + * GObjects, however, don't work like that, there's only a + * reference count but no notion of who owns the reference so, + * a JS object that's proxying a GObject is unconditionally held + * alive as long as the GObject has >1 references. + * + * Since we cannot know how many more wrapped GObjects are going + * be marked for garbage collection after the owner is destroyed, + * always queue a garbage collection when a toggle reference goes + * down. + */ + context = gjs_context_get_current(); + if (!_gjs_context_destroying(context)) + _gjs_context_schedule_gc(context); } } diff --git a/gjs/context-private.h b/gjs/context-private.h index 6dbe669..2283d01 100644 --- a/gjs/context-private.h +++ b/gjs/context-private.h @@ -57,6 +57,8 @@ bool _gjs_context_run_jobs(GjsContext *gjs_context); void _gjs_context_unregister_unhandled_promise_rejection(GjsContext *gjs_context, uint64_t promise_id); +void _gjs_context_schedule_gc(GjsContext *js_context); + G_END_DECLS void _gjs_context_register_unhandled_promise_rejection(GjsContext *gjs_context, diff --git a/gjs/context.cpp b/gjs/context.cpp index c105118..4d12e0c 100644 --- a/gjs/context.cpp +++ b/gjs/context.cpp @@ -85,6 +85,7 @@ struct _GjsContext { uint8_t exit_code; guint auto_gc_id; + bool force_gc; std::array<JS::PersistentRootedId*, GJS_STRING_LAST> const_strings; @@ -422,14 +423,24 @@ static gboolean trigger_gc_if_needed (gpointer user_data) { GjsContext *js_context = GJS_CONTEXT(user_data); + js_context->auto_gc_id = 0; - gjs_gc_if_needed(js_context->context); + + if (js_context->force_gc) + JS_GC(js_context->context); + else + gjs_gc_if_needed(js_context->context); + + js_context->force_gc = FALSE; return G_SOURCE_REMOVE; } -void -_gjs_context_schedule_gc_if_needed (GjsContext *js_context) +static void +_gjs_context_schedule_gc_internal (GjsContext *js_context, + bool force_gc) { + js_context->force_gc |= force_gc; + if (js_context->auto_gc_id > 0) return; @@ -606,6 +617,18 @@ _gjs_context_unregister_unhandled_promise_rejection(GjsContext *gjs_context, "previously marked as unhandled", erased == 1)); } +void +_gjs_context_schedule_gc (GjsContext *js_context) +{ + _gjs_context_schedule_gc_internal(js_context, TRUE); +} + +void +_gjs_context_schedule_gc_if_needed (GjsContext *js_context) +{ + _gjs_context_schedule_gc_internal(js_context, FALSE); +} + /** * gjs_context_maybe_gc: * @context: a #GjsContext
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor