GitLab repository storage has been migrated to hashed layout. Please contact Infrastructure team if you notice any issues with repositories or hooks.

Commit bf0afbd6 authored by Philip Chimento's avatar Philip Chimento 🚮

Merge branch 'gbsneto/aggressive-gc' into 'master'

Queue a GC when a toggle reference goes from >1 to 1

See merge request !114
parents a6b6fc13 e9e96955
Pipeline #9216 passed with stages
in 36 minutes and 36 seconds
......@@ -1001,8 +1001,30 @@ handle_toggle_down(GObject *gobj)
* collected by the GC
*/
if (priv->keep_alive.rooted()) {
GjsContext *context;
gjs_debug_lifecycle(GJS_DEBUG_GOBJECT, "Unrooting object");
priv->keep_alive.switch_to_unrooted();
/* 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);
}
}
......
......@@ -36,6 +36,8 @@ bool _gjs_context_destroying (GjsContext *js_context);
void _gjs_context_schedule_gc_if_needed (GjsContext *js_context);
void _gjs_context_schedule_gc(GjsContext *js_context);
void _gjs_context_exit(GjsContext *js_context,
uint8_t exit_code);
......
......@@ -90,6 +90,7 @@ struct _GjsContext {
uint8_t exit_code;
guint auto_gc_id;
bool force_gc;
std::array<JS::PersistentRootedId*, GJS_STRING_LAST> const_strings;
......@@ -592,21 +593,43 @@ 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)
{
if (js_context->auto_gc_id > 0)
return;
js_context->force_gc |= force_gc;
js_context->auto_gc_id = g_idle_add_full(G_PRIORITY_LOW,
trigger_gc_if_needed,
js_context, NULL);
}
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);
}
void
_gjs_context_exit(GjsContext *js_context,
uint8_t exit_code)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment