Hello community, here is the log from the commit of package gjs for openSUSE:Factory checked in at 2018-05-10 15:45:38 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/gjs (Old) and /work/SRC/openSUSE:Factory/.gjs.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "gjs" Thu May 10 15:45:38 2018 rev:74 rq:605077 version:1.52.3 Changes: -------- --- /work/SRC/openSUSE:Factory/gjs/gjs.changes 2018-04-22 14:37:30.057611115 +0200 +++ /work/SRC/openSUSE:Factory/.gjs.new/gjs.changes 2018-05-10 15:45:45.993253693 +0200 @@ -1,0 +2,25 @@ +Sun May 6 21:21:29 UTC 2018 - [email protected] + +- Update to version 1.52.3: + + Include calc.js example from Seed (glgo#gnome/gjs#130). + + CI: Un-pin the Fedora Docker image (glgo#gnome/gjs#141, + (glgo#gnome/gjs#131). + + Reduce overhead of wrapped objects (glgo#gnome/gjs#142, + (glgo#gnome/gjs#121). + + Various CI changes (glgo#gnome/gjs#134, (glgo#gnome/gjs#136). + +------------------------------------------------------------------- +Mon Apr 30 06:19:07 UTC 2018 - [email protected] + +- Add gjs-Add-API-to-force-GC-schedule.patch: context: Add API to + force GC schedule. There are situations where we cannot run the + GC right away, but we also cannot ignore the need of running it. + For those cases, add a new private function that forces GC to + happen on idle (glgo"GNOME/gjs#140). +- Add gjs-Queue-forced-GC.patch: object: Queue a forced GC when + toggling down. 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 (glgo"GNOME/gjs#140). + +------------------------------------------------------------------- Old: ---- gjs-1.52.2.tar.xz New: ---- gjs-1.52.3.tar.xz gjs-Add-API-to-force-GC-schedule.patch gjs-Queue-forced-GC.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ gjs.spec ++++++ --- /var/tmp/diff_new_pack.iCAd2g/_old 2018-05-10 15:45:47.277206637 +0200 +++ /var/tmp/diff_new_pack.iCAd2g/_new 2018-05-10 15:45:47.277206637 +0200 @@ -17,13 +17,17 @@ Name: gjs -Version: 1.52.2 +Version: 1.52.3 Release: 0 Summary: JavaScript bindings based on gobject-introspection and Mozilla License: MIT Group: Development/Libraries/GNOME URL: https://wiki.gnome.org/Projects/Gjs Source0: http://download.gnome.org/sources/gjs/1.52/%{name}-%{version}.tar.xz +# PATCH-FIX-UPSTREAM gjs-Add-API-to-force-GC-schedule.patch -- context: Add API to force GC schedule +Patch0: gjs-Add-API-to-force-GC-schedule.patch +# PATCH-FIX-UPSTREAM gjs-Queue-forced-GC.patch -- object: Queue a forced GC when toggling down +Patch1: gjs-Queue-forced-GC.patch BuildRequires: gcc-c++ BuildRequires: mozjs52-devel BuildRequires: pkgconfig @@ -83,7 +87,7 @@ Mozilla SpiderMonkey JavaScript engine. %prep -%setup -q +%autosetup -p1 %build %configure \ ++++++ gjs-1.52.2.tar.xz -> gjs-1.52.3.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gjs-1.52.2/NEWS new/gjs-1.52.3/NEWS --- old/gjs-1.52.2/NEWS 2018-04-18 08:45:02.000000000 +0200 +++ new/gjs-1.52.3/NEWS 2018-05-06 22:23:53.000000000 +0200 @@ -1,3 +1,14 @@ +Version 1.52.3 +-------------- + +- Closed bugs and merge requests: + + * Include calc.js example from Seed [!130, William Barath, Philip Chimento] + * CI: Un-pin the Fedora Docker image [#141, !131, Claudio André] + * Reduce overhead of wrapped objects [#142, !121, Carlos Garnacho, Philip + Chimento] + * Various CI changes [!134, !136, Claudio André] + Version 1.52.2 -------------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gjs-1.52.2/configure new/gjs-1.52.3/configure --- old/gjs-1.52.2/configure 2018-04-18 08:19:57.000000000 +0200 +++ new/gjs-1.52.3/configure 2018-05-06 23:08:23.000000000 +0200 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for gjs 1.52.2. +# Generated by GNU Autoconf 2.69 for gjs 1.52.3. # # Report bugs to <http://bugzilla.gnome.org/enter_bug.cgi?product=gjs>. # @@ -591,8 +591,8 @@ # Identity of this package. PACKAGE_NAME='gjs' PACKAGE_TARNAME='gjs' -PACKAGE_VERSION='1.52.2' -PACKAGE_STRING='gjs 1.52.2' +PACKAGE_VERSION='1.52.3' +PACKAGE_STRING='gjs 1.52.3' PACKAGE_BUGREPORT='http://bugzilla.gnome.org/enter_bug.cgi?product=gjs' PACKAGE_URL='https://wiki.gnome.org/Projects/Gjs' @@ -1451,7 +1451,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures gjs 1.52.2 to adapt to many kinds of systems. +\`configure' configures gjs 1.52.3 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1521,7 +1521,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of gjs 1.52.2:";; + short | recursive ) echo "Configuration of gjs 1.52.3:";; esac cat <<\_ACEOF @@ -1700,7 +1700,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -gjs configure 1.52.2 +gjs configure 1.52.3 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2251,7 +2251,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by gjs $as_me 1.52.2, which was +It was created by gjs $as_me 1.52.3, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -3114,7 +3114,7 @@ # Define the identity of the package. PACKAGE='gjs' - VERSION='1.52.2' + VERSION='1.52.3' cat >>confdefs.h <<_ACEOF @@ -3341,10 +3341,10 @@ -GJS_VERSION=15202 +GJS_VERSION=15203 -$as_echo "#define GJS_VERSION (1 * 100 + 52) * 100 + 2" >>confdefs.h +$as_echo "#define GJS_VERSION (1 * 100 + 52) * 100 + 3" >>confdefs.h GETTEXT_PACKAGE=gjs @@ -23346,7 +23346,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by gjs $as_me 1.52.2, which was +This file was extended by gjs $as_me 1.52.3, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -23417,7 +23417,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -gjs config.status 1.52.2 +gjs config.status 1.52.3 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gjs-1.52.2/configure.ac new/gjs-1.52.3/configure.ac --- old/gjs-1.52.2/configure.ac 2018-04-18 08:13:46.000000000 +0200 +++ new/gjs-1.52.3/configure.ac 2018-05-06 21:53:56.000000000 +0200 @@ -3,7 +3,7 @@ m4_define(pkg_major_version, 1) m4_define(pkg_minor_version, 52) -m4_define(pkg_micro_version, 2) +m4_define(pkg_micro_version, 3) m4_define(pkg_version, pkg_major_version.pkg_minor_version.pkg_micro_version) m4_define(pkg_int_version, (pkg_major_version * 100 + pkg_minor_version) * 100 + pkg_micro_version) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gjs-1.52.2/gi/object.cpp new/gjs-1.52.3/gi/object.cpp --- old/gjs-1.52.2/gi/object.cpp 2018-04-18 08:13:46.000000000 +0200 +++ new/gjs-1.52.3/gi/object.cpp 2018-05-06 22:07:28.000000000 +0200 @@ -54,6 +54,65 @@ #include <util/log.h> #include <girepository.h> +typedef class GjsListLink GjsListLink; +typedef struct ObjectInstance ObjectInstance; + +static GjsListLink* object_instance_get_link(ObjectInstance *priv); + +class GjsListLink { + private: + ObjectInstance *m_prev; + ObjectInstance *m_next; + + public: + ObjectInstance* prev() { + return m_prev; + } + + ObjectInstance* next() { + return m_next; + } + + void prepend(ObjectInstance *this_instance, + ObjectInstance *head) { + GjsListLink *elem = object_instance_get_link(head); + + g_assert(object_instance_get_link(this_instance) == this); + + if (elem->m_prev) { + GjsListLink *prev = object_instance_get_link(elem->m_prev); + prev->m_next = this_instance; + this->m_prev = elem->m_prev; + } + + elem->m_prev = this_instance; + this->m_next = head; + } + + void unlink() { + if (m_prev) + object_instance_get_link(m_prev)->m_next = m_next; + if (m_next) + object_instance_get_link(m_next)->m_prev = m_prev; + + m_prev = m_next = NULL; + } + + int size() { + GjsListLink *elem = this; + int count = 0; + + do { + count++; + if (!elem->m_next) + break; + elem = object_instance_get_link(elem->m_next); + } while (elem); + + return count; + } +}; + struct ObjectInstance { GIObjectInfo *info; GObject *gobj; /* NULL if we are the prototype and not an instance */ @@ -68,6 +127,8 @@ prototypes) */ GTypeClass *klass; + GjsListLink instance_link; + unsigned js_object_finalized : 1; unsigned g_object_finalized : 1; }; @@ -79,7 +140,7 @@ static std::unordered_map<GType, ParamRefArray> class_init_properties; static bool weak_pointer_callback = false; -static std::set<ObjectInstance *> wrapped_gobject_list; +ObjectInstance *wrapped_gobject_list; extern struct JSClass gjs_object_instance_class; GJS_DEFINE_PRIV_FROM_JS(ObjectInstance, gjs_object_instance_class) @@ -945,6 +1006,28 @@ return true; } +static GjsListLink * +object_instance_get_link(ObjectInstance *priv) +{ + return &priv->instance_link; +} + +static void +object_instance_unlink(ObjectInstance *priv) +{ + if (wrapped_gobject_list == priv) + wrapped_gobject_list = priv->instance_link.next(); + priv->instance_link.unlink(); +} + +static void +object_instance_link(ObjectInstance *priv) +{ + if (wrapped_gobject_list) + priv->instance_link.prepend(priv, wrapped_gobject_list); + wrapped_gobject_list = priv; +} + static void wrapped_gobj_dispose_notify(gpointer data, GObject *where_the_object_was) @@ -952,7 +1035,7 @@ auto *priv = static_cast<ObjectInstance *>(data); priv->g_object_finalized = true; - wrapped_gobject_list.erase(priv); + object_instance_unlink(priv); gjs_debug_lifecycle(GJS_DEBUG_GOBJECT, "Wrapped GObject %p disposed", where_the_object_was); } @@ -971,7 +1054,7 @@ G_OBJECT_TYPE_NAME(priv->gobj)); priv->keep_alive.reset(); - wrapped_gobject_list.erase(priv); + object_instance_unlink(priv); } static void @@ -1156,14 +1239,15 @@ * toggle ref removal -> gobj dispose -> toggle ref notify * by emptying the toggle queue earlier in the shutdown sequence. */ std::vector<ObjectInstance *> to_be_released; - for (auto iter = wrapped_gobject_list.begin(); iter != wrapped_gobject_list.end(); ) { - ObjectInstance *priv = *iter; - if (priv->keep_alive.rooted()) { - to_be_released.push_back(priv); - iter = wrapped_gobject_list.erase(iter); - } else { - iter++; + ObjectInstance *link = wrapped_gobject_list; + while (link) { + ObjectInstance *next = link->instance_link.next(); + if (link->keep_alive.rooted()) { + to_be_released.push_back(link); + object_instance_unlink(link); } + + link = next; } for (ObjectInstance *priv : to_be_released) release_native_object(priv); @@ -1209,16 +1293,17 @@ { gjs_debug_lifecycle(GJS_DEBUG_GOBJECT, "Weak pointer update callback, " "%zu wrapped GObject(s) to examine", - wrapped_gobject_list.size()); + wrapped_gobject_list->instance_link.size()); std::vector<GObject *> to_be_disassociated; + ObjectInstance *priv = wrapped_gobject_list; - for (auto iter = wrapped_gobject_list.begin(); iter != wrapped_gobject_list.end(); ) { - ObjectInstance *priv = *iter; - if (priv->keep_alive.rooted() || priv->keep_alive == nullptr || - !priv->keep_alive.update_after_gc()) { - iter++; - } else { + while (priv) { + ObjectInstance *next = priv->instance_link.next(); + + if (!priv->keep_alive.rooted() && + priv->keep_alive != nullptr && + priv->keep_alive.update_after_gc()) { /* Ouch, the JS object is dead already. Disassociate the * GObject and hope the GObject dies too. (Remove it from * the weak pointer list first, since the disassociation @@ -1229,8 +1314,10 @@ "%p (%s)", priv->keep_alive.get(), priv->gobj, G_OBJECT_TYPE_NAME(priv->gobj)); to_be_disassociated.push_back(priv->gobj); - iter = wrapped_gobject_list.erase(iter); + object_instance_unlink(priv); } + + priv = next; } for (GObject *gobj : to_be_disassociated) @@ -1263,7 +1350,7 @@ set_object_qdata(gobj, priv); ensure_weak_pointer_callback(context); - wrapped_gobject_list.insert(priv); + object_instance_link(priv); g_object_weak_ref(gobj, wrapped_gobj_dispose_notify, priv); @@ -1541,7 +1628,7 @@ priv->keep_alive.reset(); } - wrapped_gobject_list.erase(priv); + object_instance_unlink(priv); if (priv->info) { g_base_info_unref( (GIBaseInfo*) priv->info); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gjs-1.52.2/gjs/jsapi-util-root.h new/gjs-1.52.3/gjs/jsapi-util-root.h --- old/gjs-1.52.2/gjs/jsapi-util-root.h 2018-03-29 08:04:18.000000000 +0200 +++ new/gjs-1.52.3/gjs/jsapi-util-root.h 2018-05-06 22:07:34.000000000 +0200 @@ -219,6 +219,7 @@ return m_root->get() == nullptr; return m_heap.unbarrieredGet() == nullptr; } + inline bool operator!=(std::nullptr_t) const { return !(*this == nullptr); } /* You can get a Handle<T> if the thing is rooted, so that you can use this * wrapper with stack rooting. However, you must not do this if the diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gjs-1.52.2/win32/config.h.win32 new/gjs-1.52.3/win32/config.h.win32 --- old/gjs-1.52.2/win32/config.h.win32 2018-04-18 08:20:16.000000000 +0200 +++ new/gjs-1.52.3/win32/config.h.win32 2018-05-06 23:08:47.000000000 +0200 @@ -13,7 +13,7 @@ #define GETTEXT_PACKAGE "gjs" /* The gjs version as an integer */ -#define GJS_VERSION 15202 +#define GJS_VERSION 15203 /* define if the compiler supports basic C++11 syntax */ #define HAVE_CXX11 1 @@ -74,7 +74,7 @@ #define PACKAGE_NAME "gjs" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "gjs 1.52.2" +#define PACKAGE_STRING "gjs 1.52.3" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "gjs" @@ -83,10 +83,10 @@ #define PACKAGE_URL "" /* Define to the version of this package. */ -#define PACKAGE_VERSION "1.52.2" +#define PACKAGE_VERSION "1.52.3" /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* Version number of package */ -#define VERSION "1.52.2" +#define VERSION "1.52.3" ++++++ gjs-Add-API-to-force-GC-schedule.patch ++++++ >From 090298512b12e76929bf8bd14dccbfd355f78dce Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto <[email protected]> Date: Fri, 30 Mar 2018 21:37:37 -0300 Subject: [PATCH] context: Add API to force GC schedule There are situations where we cannot run the GC right away, but we also cannot ignore the need of running it. For those cases, add a new private function that forces GC to happen on idle. --- gjs/context-private.h | 2 ++ gjs/context.cpp | 29 +++++++++++++++++++++++++---- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/gjs/context-private.h b/gjs/context-private.h index 6dbe669..c45c8d0 100644 --- a/gjs/context-private.h +++ b/gjs/context-private.h @@ -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); diff --git a/gjs/context.cpp b/gjs/context.cpp index c509943..77d7eaa 100644 --- a/gjs/context.cpp +++ b/gjs/context.cpp @@ -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,22 +593,42 @@ 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); + 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; + g_source_remove(js_context->auto_gc_id); + 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) { -- libgit2 0.27.0 ++++++ gjs-Queue-forced-GC.patch ++++++ >From e9e969553866b0dd29e78b41c0e372569405f46c Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto <[email protected]> Date: Wed, 28 Mar 2018 19:21:52 -0300 Subject: [PATCH] object: Queue a forced GC when toggling down 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. Issue: #140 --- gi/object.cpp | 22 ++++++++++++++++++++++ gjs/context-private.h | 2 +- gjs/context.cpp | 14 ++++++++------ 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/gi/object.cpp b/gi/object.cpp index 3fdfced..606a918 100644 --- a/gi/object.cpp +++ b/gi/object.cpp @@ -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); } } diff --git a/gjs/context-private.h b/gjs/context-private.h index c45c8d0..49c0cf9 100644 --- a/gjs/context-private.h +++ b/gjs/context-private.h @@ -36,7 +36,7 @@ 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_schedule_gc(GjsContext *js_context); void _gjs_context_exit(GjsContext *js_context, uint8_t exit_code); diff --git a/gjs/context.cpp b/gjs/context.cpp index 77d7eaa..a2ce34a 100644 --- a/gjs/context.cpp +++ b/gjs/context.cpp @@ -599,31 +599,33 @@ trigger_gc_if_needed (gpointer user_data) else gjs_gc_if_needed(js_context->context); + js_context->force_gc = false; + return G_SOURCE_REMOVE; } static void -_gjs_context_schedule_gc_internal (GjsContext *js_context, - bool force_gc) +_gjs_context_schedule_gc_internal(GjsContext *js_context, + bool force_gc) { if (js_context->auto_gc_id > 0) - g_source_remove(js_context->auto_gc_id); + return; - js_context->force_gc = force_gc; + 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(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_if_needed(GjsContext *js_context) { _gjs_context_schedule_gc_internal(js_context, false); } -- libgit2 0.27.0
