diff --git a/.gitignore b/.gitignore index 1dc7400..456a702 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/gjs-1.52.5.tar.xz +SOURCES/gjs-1.56.2.tar.xz diff --git a/.gjs.metadata b/.gjs.metadata index 7cabe98..ed23f03 100644 --- a/.gjs.metadata +++ b/.gjs.metadata @@ -1 +1 @@ -a133292bdc6e922b30679f7de9364ec847599b03 SOURCES/gjs-1.52.5.tar.xz +cf4f885d2d41a5c9fb85bd90df46bb67a93f4f07 SOURCES/gjs-1.56.2.tar.xz diff --git a/SOURCES/0001-cairo-context-Special-case-0-sized-vector.patch b/SOURCES/0001-cairo-context-Special-case-0-sized-vector.patch deleted file mode 100644 index 04ef188..0000000 --- a/SOURCES/0001-cairo-context-Special-case-0-sized-vector.patch +++ /dev/null @@ -1,28 +0,0 @@ -From c47b4f6993f1cd7fb346f0e09a0fabb0a158039b Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Fri, 22 Feb 2019 14:16:17 +0100 -Subject: [PATCH] cairo-context: Special-case 0-sized vector - ---- - modules/cairo-context.cpp | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/modules/cairo-context.cpp b/modules/cairo-context.cpp -index e77bde16..35d798a6 100644 ---- a/modules/cairo-context.cpp -+++ b/modules/cairo-context.cpp -@@ -582,7 +582,10 @@ setDash_func(JSContext *context, - dashes_c.push_back(b); - } - -- cairo_set_dash(cr, &dashes_c[0], dashes_c.size(), offset); -+ if (dashes_c.size() == 0) -+ cairo_set_dash(cr, NULL, 0, offset); -+ else -+ cairo_set_dash(cr, &dashes_c[0], dashes_c.size(), offset); - argv.rval().setUndefined(); - return true; - } --- -2.20.1 - diff --git a/SOURCES/0001-gi-Include-missing-glib-bits.patch b/SOURCES/0001-gi-Include-missing-glib-bits.patch new file mode 100644 index 0000000..4fd11ed --- /dev/null +++ b/SOURCES/0001-gi-Include-missing-glib-bits.patch @@ -0,0 +1,1581 @@ +From 9d7d64617c59e99bd2aced57009213c8a99e676e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 29 May 2019 19:44:55 +0200 +Subject: [PATCH] gi: Include missing glib bits + +--- + gi/garcbox.c | 387 ++++++++++++++++++++++++++++++++++ + gi/grcbox.c | 506 +++++++++++++++++++++++++++++++++++++++++++++ + gi/grcbox.h | 96 +++++++++ + gi/grcboxprivate.h | 78 +++++++ + gi/grefcount.c | 289 ++++++++++++++++++++++++++ + gi/grefcount.h | 134 ++++++++++++ + gi/wrapperutils.h | 2 + + gjs-srcs.mk | 6 + + 8 files changed, 1498 insertions(+) + create mode 100644 gi/garcbox.c + create mode 100644 gi/grcbox.c + create mode 100644 gi/grcbox.h + create mode 100644 gi/grcboxprivate.h + create mode 100644 gi/grefcount.c + create mode 100644 gi/grefcount.h + +diff --git a/gi/garcbox.c b/gi/garcbox.c +new file mode 100644 +index 00000000..bee75073 +--- /dev/null ++++ b/gi/garcbox.c +@@ -0,0 +1,387 @@ ++/* garcbox.c: Atomically reference counted data ++ * ++ * Copyright 2018 Emmanuele Bassi ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see . ++ */ ++ ++#include "config.h" ++ ++#include "grcboxprivate.h" ++ ++#if 0 ++#include "gmessages.h" ++#endif ++#include "grefcount.h" ++ ++#ifdef ENABLE_VALGRIND ++#include "valgrind.h" ++#endif ++ ++#if 0 ++#include "glib_trace.h" ++#else ++#include "gjs_gi_trace.h" ++#endif ++ ++#include ++ ++#define G_ARC_BOX(p) (GArcBox *) (((char *) (p)) - G_ARC_BOX_SIZE) ++ ++/** ++ * SECTION:arcbox ++ * @Title: Atomically reference counted data ++ * @Short_description: Allocated memory with atomic reference counting semantics ++ * ++ * An "atomically reference counted box", or "ArcBox", is an opaque wrapper ++ * data type that is guaranteed to be as big as the size of a given data type, ++ * and which augments the given data type with thread safe reference counting ++ * semantics for its memory management. ++ * ++ * ArcBox is useful if you have a plain old data type, like a structure ++ * typically placed on the stack, and you wish to provide additional API ++ * to use it on the heap; or if you want to implement a new type to be ++ * passed around by reference without necessarily implementing copy/free ++ * semantics or your own reference counting. ++ * ++ * The typical use is: ++ * ++ * |[ ++ * typedef struct { ++ * char *name; ++ * char *address; ++ * char *city; ++ * char *state; ++ * int age; ++ * } Person; ++ * ++ * Person * ++ * person_new (void) ++ * { ++ * return g_atomic_rc_box_new0 (Person); ++ * } ++ * ]| ++ * ++ * Every time you wish to acquire a reference on the memory, you should ++ * call g_atomic_rc_box_acquire(); similarly, when you wish to release a reference ++ * you should call g_atomic_rc_box_release(): ++ * ++ * |[ ++ * // Add a Person to the Database; the Database acquires ownership ++ * // of the Person instance ++ * void ++ * add_person_to_database (Database *db, Person *p) ++ * { ++ * db->persons = g_list_prepend (db->persons, g_atomic_rc_box_acquire (p)); ++ * } ++ * ++ * // Removes a Person from the Database; the reference acquired by ++ * // add_person_to_database() is released here ++ * void ++ * remove_person_from_database (Database *db, Person *p) ++ * { ++ * db->persons = g_list_remove (db->persons, p); ++ * g_atomic_rc_box_release (p); ++ * } ++ * ]| ++ * ++ * If you have additional memory allocated inside the structure, you can ++ * use g_atomic_rc_box_release_full(), which takes a function pointer, which ++ * will be called if the reference released was the last: ++ * ++ * |[ ++ * void ++ * person_clear (Person *p) ++ * { ++ * g_free (p->name); ++ * g_free (p->address); ++ * g_free (p->city); ++ * g_free (p->state); ++ * } ++ * ++ * void ++ * remove_person_from_database (Database *db, Person *p) ++ * { ++ * db->persons = g_list_remove (db->persons, p); ++ * g_atomic_rc_box_release_full (p, (GDestroyNotify) person_clear); ++ * } ++ * ]| ++ * ++ * If you wish to transfer the ownership of a reference counted data ++ * type without increasing the reference count, you can use g_steal_pointer(): ++ * ++ * |[ ++ * Person *p = g_atomic_rc_box_new (Person); ++ * ++ * fill_person_details (p); ++ * ++ * add_person_to_database (db, g_steal_pointer (&p)); ++ * ]| ++ * ++ * ## Thread safety ++ * ++ * The reference counting operations on data allocated using g_atomic_rc_box_alloc(), ++ * g_atomic_rc_box_new(), and g_atomic_rc_box_dup() are guaranteed to be atomic, and thus ++ * can be safely be performed by different threads. It is important to note that ++ * only the reference acquisition and release are atomic; changes to the content ++ * of the data are your responsibility. ++ * ++ * ## Automatic pointer clean up ++ * ++ * If you want to add g_autoptr() support to your plain old data type through ++ * reference counting, you can use the G_DEFINE_AUTOPTR_CLEANUP_FUNC() and ++ * g_atomic_rc_box_release(): ++ * ++ * |[ ++ * G_DEFINE_AUTOPTR_CLEANUP_FUNC (MyDataStruct, g_atomic_rc_box_release) ++ * ]| ++ * ++ * If you need to clear the contents of the data, you will need to use an ++ * ancillary function that calls g_rc_box_release_full(): ++ * ++ * |[ ++ * static void ++ * my_data_struct_release (MyDataStruct *data) ++ * { ++ * // my_data_struct_clear() is defined elsewhere ++ * g_atomic_rc_box_release_full (data, (GDestroyNotify) my_data_struct_clear); ++ * } ++ * ++ * G_DEFINE_AUTOPTR_CLEANUP_FUNC (MyDataStruct, my_data_struct_release) ++ * ]| ++ * ++ * Since: 2.58. ++ */ ++ ++/** ++ * g_atomic_rc_box_alloc: ++ * @block_size: the size of the allocation, must be greater than 0 ++ * ++ * Allocates @block_size bytes of memory, and adds atomic ++ * reference counting semantics to it. ++ * ++ * The data will be freed when its reference count drops to ++ * zero. ++ * ++ * The allocated data is guaranteed to be suitably aligned for any ++ * built-in type. ++ * ++ * Returns: (transfer full) (not nullable): a pointer to the allocated memory ++ * ++ * Since: 2.58 ++ */ ++gpointer ++g_atomic_rc_box_alloc (gsize block_size) ++{ ++ g_return_val_if_fail (block_size > 0, NULL); ++ ++ return g_rc_box_alloc_full (block_size, STRUCT_ALIGNMENT, TRUE, FALSE); ++} ++ ++/** ++ * g_atomic_rc_box_alloc0: ++ * @block_size: the size of the allocation, must be greater than 0 ++ * ++ * Allocates @block_size bytes of memory, and adds atomic ++ * referenc counting semantics to it. ++ * ++ * The contents of the returned data is set to zero. ++ * ++ * The data will be freed when its reference count drops to ++ * zero. ++ * ++ * The allocated data is guaranteed to be suitably aligned for any ++ * built-in type. ++ * ++ * Returns: (transfer full) (not nullable): a pointer to the allocated memory ++ * ++ * Since: 2.58 ++ */ ++gpointer ++g_atomic_rc_box_alloc0 (gsize block_size) ++{ ++ g_return_val_if_fail (block_size > 0, NULL); ++ ++ return g_rc_box_alloc_full (block_size, STRUCT_ALIGNMENT, TRUE, TRUE); ++} ++ ++/** ++ * g_atomic_rc_box_new: ++ * @type: the type to allocate, typically a structure name ++ * ++ * A convenience macro to allocate atomically reference counted ++ * data with the size of the given @type. ++ * ++ * This macro calls g_atomic_rc_box_alloc() with `sizeof (@type)` and ++ * casts the returned pointer to a pointer of the given @type, ++ * avoiding a type cast in the source code. ++ * ++ * Returns: (transfer full) (not nullable): a pointer to the allocated ++ * memory, cast to a pointer for the given @type ++ * ++ * Since: 2.58 ++ */ ++ ++/** ++ * g_atomic_rc_box_new0: ++ * @type: the type to allocate, typically a structure name ++ * ++ * A convenience macro to allocate atomically reference counted ++ * data with the size of the given @type, and set its contents ++ * to zero. ++ * ++ * This macro calls g_atomic_rc_box_alloc0() with `sizeof (@type)` and ++ * casts the returned pointer to a pointer of the given @type, ++ * avoiding a type cast in the source code. ++ * ++ * Returns: (transfer full) (not nullable): a pointer to the allocated ++ * memory, cast to a pointer for the given @type ++ * ++ * Since: 2.58 ++ */ ++ ++/** ++ * g_atomic_rc_box_dup: ++ * @block_size: the number of bytes to copy, must be greater than 0 ++ * @mem_block: (not nullable): the memory to copy ++ * ++ * Allocates a new block of data with atomit reference counting ++ * semantics, and copies @block_size bytes of @mem_block ++ * into it. ++ * ++ * Returns: (transfer full) (not nullable): a pointer to the allocated ++ * memory ++ * ++ * Since: 2.58 ++ */ ++gpointer ++(g_atomic_rc_box_dup) (gsize block_size, ++ gconstpointer mem_block) ++{ ++ gpointer res; ++ ++ g_return_val_if_fail (block_size > 0, NULL); ++ g_return_val_if_fail (mem_block != NULL, NULL); ++ ++ res = g_rc_box_alloc_full (block_size, STRUCT_ALIGNMENT, TRUE, FALSE); ++ memcpy (res, mem_block, block_size); ++ ++ return res; ++} ++ ++/** ++ * g_atomic_rc_box_acquire: ++ * @mem_block: (not nullable): a pointer to reference counted data ++ * ++ * Atomically acquires a reference on the data pointed by @mem_block. ++ * ++ * Returns: (transfer full) (not nullable): a pointer to the data, ++ * with its reference count increased ++ * ++ * Since: 2.58 ++ */ ++gpointer ++(g_atomic_rc_box_acquire) (gpointer mem_block) ++{ ++ GArcBox *real_box = G_ARC_BOX (mem_block); ++ ++ g_return_val_if_fail (mem_block != NULL, NULL); ++#ifndef G_DISABLE_ASSERT ++ g_return_val_if_fail (real_box->magic == G_BOX_MAGIC, NULL); ++#endif ++ ++ g_atomic_ref_count_inc (&real_box->ref_count); ++ ++ TRACE (GLIB_RCBOX_ACQUIRE (mem_block, 1)); ++ ++ return mem_block; ++} ++ ++/** ++ * g_atomic_rc_box_release: ++ * @mem_block: (transfer full) (not nullable): a pointer to reference counted data ++ * ++ * Atomically releases a reference on the data pointed by @mem_block. ++ * ++ * If the reference was the last one, it will free the ++ * resources allocated for @mem_block. ++ * ++ * Since: 2.58 ++ */ ++void ++g_atomic_rc_box_release (gpointer mem_block) ++{ ++ g_atomic_rc_box_release_full (mem_block, NULL); ++} ++ ++/** ++ * g_atomic_rc_box_release_full: ++ * @mem_block: (transfer full) (not nullable): a pointer to reference counted data ++ * @clear_func: (not nullable): a function to call when clearing the data ++ * ++ * Atomically releases a reference on the data pointed by @mem_block. ++ * ++ * If the reference was the last one, it will call @clear_func ++ * to clear the contents of @mem_block, and then will free the ++ * resources allocated for @mem_block. ++ * ++ * Since: 2.58 ++ */ ++void ++g_atomic_rc_box_release_full (gpointer mem_block, ++ GDestroyNotify clear_func) ++{ ++ GArcBox *real_box = G_ARC_BOX (mem_block); ++ ++ g_return_if_fail (mem_block != NULL); ++#ifndef G_DISABLE_ASSERT ++ g_return_if_fail (real_box->magic == G_BOX_MAGIC); ++#endif ++ ++ if (g_atomic_ref_count_dec (&real_box->ref_count)) ++ { ++ char *real_mem = (char *) real_box - real_box->private_offset; ++ ++ TRACE (GLIB_RCBOX_RELEASE (mem_block, 1)); ++ ++ if (clear_func != NULL) ++ clear_func (mem_block); ++ ++ TRACE (GLIB_RCBOX_FREE (mem_block)); ++ g_free (real_mem); ++ } ++} ++ ++/** ++ * g_atomic_rc_box_get_size: ++ * @mem_block: (not nullable): a pointer to reference counted data ++ * ++ * Retrieves the size of the reference counted data pointed by @mem_block. ++ * ++ * Returns: the size of the data, in bytes ++ * ++ * Since: 2.58 ++ */ ++gsize ++g_atomic_rc_box_get_size (gpointer mem_block) ++{ ++ GArcBox *real_box = G_ARC_BOX (mem_block); ++ ++ g_return_val_if_fail (mem_block != NULL, 0); ++#ifndef G_DISABLE_ASSERT ++ g_return_val_if_fail (real_box->magic == G_BOX_MAGIC, 0); ++#endif ++ ++ return real_box->mem_size; ++} +diff --git a/gi/grcbox.c b/gi/grcbox.c +new file mode 100644 +index 00000000..4f76a2b5 +--- /dev/null ++++ b/gi/grcbox.c +@@ -0,0 +1,506 @@ ++/* grcbox.c: Reference counted data ++ * ++ * Copyright 2018 Emmanuele Bassi ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see . ++ */ ++ ++#include "config.h" ++ ++#include "grcboxprivate.h" ++ ++#include "grefcount.h" ++#if 0 ++#include "gmessages.h" ++#include "gtestutils.h" ++ ++#include "glib_trace.h" ++#else ++#include "gjs_gi_trace.h" ++#endif ++ ++#ifdef ENABLE_VALGRIND ++#include "valgrind.h" ++#endif ++ ++#include ++ ++/** ++ * SECTION:rcbox ++ * @Title: Reference counted data ++ * @Short_description: Allocated memory with reference counting semantics ++ * ++ * A "reference counted box", or "RcBox", is an opaque wrapper data type ++ * that is guaranteed to be as big as the size of a given data type, and ++ * which augments the given data type with reference counting semantics ++ * for its memory management. ++ * ++ * RcBox is useful if you have a plain old data type, like a structure ++ * typically placed on the stack, and you wish to provide additional API ++ * to use it on the heap; or if you want to implement a new type to be ++ * passed around by reference without necessarily implementing copy/free ++ * semantics or your own reference counting. ++ * ++ * The typical use is: ++ * ++ * |[ ++ * typedef struct { ++ * char *name; ++ * char *address; ++ * char *city; ++ * char *state; ++ * int age; ++ * } Person; ++ * ++ * Person * ++ * person_new (void) ++ * { ++ * return g_rc_box_new0 (Person); ++ * } ++ * ]| ++ * ++ * Every time you wish to acquire a reference on the memory, you should ++ * call g_rc_box_acquire(); similarly, when you wish to release a reference ++ * you should call g_rc_box_release(): ++ * ++ * |[ ++ * // Add a Person to the Database; the Database acquires ownership ++ * // of the Person instance ++ * void ++ * add_person_to_database (Database *db, Person *p) ++ * { ++ * db->persons = g_list_prepend (db->persons, g_rc_box_acquire (p)); ++ * } ++ * ++ * // Removes a Person from the Database; the reference acquired by ++ * // add_person_to_database() is released here ++ * void ++ * remove_person_from_database (Database *db, Person *p) ++ * { ++ * db->persons = g_list_remove (db->persons, p); ++ * g_rc_box_release (p); ++ * } ++ * ]| ++ * ++ * If you have additional memory allocated inside the structure, you can ++ * use g_rc_box_release_full(), which takes a function pointer, which ++ * will be called if the reference released was the last: ++ * ++ * |[ ++ * void ++ * person_clear (Person *p) ++ * { ++ * g_free (p->name); ++ * g_free (p->address); ++ * g_free (p->city); ++ * g_free (p->state); ++ * } ++ * ++ * void ++ * remove_person_from_database (Database *db, Person *p) ++ * { ++ * db->persons = g_list_remove (db->persons, p); ++ * g_rc_box_release_full (p, (GDestroyNotify) person_clear); ++ * } ++ * ]| ++ * ++ * If you wish to transfer the ownership of a reference counted data ++ * type without increasing the reference count, you can use g_steal_pointer(): ++ * ++ * |[ ++ * Person *p = g_rc_box_new (Person); ++ * ++ * // fill_person_details() is defined elsewhere ++ * fill_person_details (p); ++ * ++ * // add_person_to_database_no_ref() is defined elsewhere; it adds ++ * // a Person to the Database without taking a reference ++ * add_person_to_database_no_ref (db, g_steal_pointer (&p)); ++ * ]| ++ * ++ * ## Thread safety ++ * ++ * The reference counting operations on data allocated using g_rc_box_alloc(), ++ * g_rc_box_new(), and g_rc_box_dup() are not thread safe; it is your code's ++ * responsibility to ensure that references are acquired are released on the ++ * same thread. ++ * ++ * If you need thread safe reference counting, see the [atomic reference counted ++ * data][arcbox] API. ++ * ++ * ## Automatic pointer clean up ++ * ++ * If you want to add g_autoptr() support to your plain old data type through ++ * reference counting, you can use the G_DEFINE_AUTOPTR_CLEANUP_FUNC() and ++ * g_rc_box_release(): ++ * ++ * |[ ++ * G_DEFINE_AUTOPTR_CLEANUP_FUNC (MyDataStruct, g_rc_box_release) ++ * ]| ++ * ++ * If you need to clear the contents of the data, you will need to use an ++ * ancillary function that calls g_rc_box_release_full(): ++ * ++ * |[ ++ * static void ++ * my_data_struct_release (MyDataStruct *data) ++ * { ++ * // my_data_struct_clear() is defined elsewhere ++ * g_rc_box_release_full (data, (GDestroyNotify) my_data_struct_clear); ++ * } ++ * ++ * G_DEFINE_AUTOPTR_CLEANUP_FUNC (MyDataStruct, my_data_struct_release) ++ * ]| ++ * ++ * Since: 2.58. ++ */ ++ ++/* We use the same alignment as GTypeInstance and GNU libc's malloc */ ++#define ALIGN_STRUCT(offset) ((offset + (STRUCT_ALIGNMENT - 1)) & -STRUCT_ALIGNMENT) ++ ++#define G_RC_BOX(p) (GRcBox *) (((char *) (p)) - G_RC_BOX_SIZE) ++ ++gpointer ++g_rc_box_alloc_full (gsize block_size, ++ gsize alignment, ++ gboolean atomic, ++ gboolean clear) ++{ ++ /* We don't do an (atomic ? G_ARC_BOX_SIZE : G_RC_BOX_SIZE) check, here ++ * because we have a static assertion that sizeof(GArcBox) == sizeof(GRcBox) ++ * inside grcboxprivate.h, and we don't want the compiler to unnecessarily ++ * warn about both branches of the conditional yielding identical results ++ */ ++ gsize private_size = G_ARC_BOX_SIZE; ++ gsize private_offset = 0; ++ gsize real_size; ++ char *allocated; ++ ++ g_assert (alignment != 0); ++ ++ /* We need to ensure that the private data is aligned */ ++ if (private_size % alignment != 0) ++ { ++ private_offset = private_size % alignment; ++ private_size += (alignment - private_offset); ++ } ++ ++ g_assert (block_size < (G_MAXSIZE - private_size)); ++ real_size = private_size + block_size; ++ ++ /* The real allocated size must be a multiple of @alignment, to ++ * maintain the alignment of block_size ++ */ ++ if (real_size % alignment != 0) ++ { ++ gsize offset = real_size % alignment; ++ g_assert (real_size < (G_MAXSIZE - (alignment - offset))); ++ real_size += (alignment - offset); ++ } ++ ++#ifdef ENABLE_VALGRIND ++ if (RUNNING_ON_VALGRIND) ++ { ++ /* When running under Valgrind we massage the memory allocation ++ * to include a pointer at the tail end of the block; the pointer ++ * is then set to the start of the block. This trick allows ++ * Valgrind to keep track of the over-allocation and not be ++ * confused when passing the pointer around ++ */ ++ g_assert (private_size < (G_MAXSIZE - ALIGN_STRUCT (1))); ++ private_size += ALIGN_STRUCT (1); ++ ++ if (clear) ++ allocated = g_malloc0 (real_size + sizeof (gpointer)); ++ else ++ allocated = g_malloc (real_size + sizeof (gpointer)); ++ ++ *(gpointer *) (allocated + private_size + block_size) = allocated + ALIGN_STRUCT (1); ++ ++ VALGRIND_MALLOCLIKE_BLOCK (allocated + private_size, block_size + sizeof (gpointer), 0, TRUE); ++ VALGRIND_MALLOCLIKE_BLOCK (allocated + ALIGN_STRUCT (1), private_size - ALIGN_STRUCT (1), 0, TRUE); ++ } ++ else ++#endif /* ENABLE_VALGRIND */ ++ { ++ if (clear) ++ allocated = g_malloc0 (real_size); ++ else ++ allocated = g_malloc (real_size); ++ } ++ ++ if (atomic) ++ { ++ /* We leave the alignment padding at the top of the allocation, ++ * so we have an in memory layout of: ++ * ++ * |[ offset ][ sizeof(GArcBox) ]||[ block_size ]| ++ */ ++ GArcBox *real_box = (GArcBox *) (allocated + private_offset); ++ /* Store the real size */ ++ real_box->mem_size = block_size; ++ /* Store the alignment offset, to be used when freeing the ++ * allocated block ++ */ ++ real_box->private_offset = private_offset; ++#ifndef G_DISABLE_ASSERT ++ real_box->magic = G_BOX_MAGIC; ++#endif ++ g_atomic_ref_count_init (&real_box->ref_count); ++ } ++ else ++ { ++ /* We leave the alignment padding at the top of the allocation, ++ * so we have an in memory layout of: ++ * ++ * |[ offset ][ sizeof(GRcBox) ]||[ block_size ]| ++ */ ++ GRcBox *real_box = (GRcBox *) (allocated + private_offset); ++ /* Store the real size */ ++ real_box->mem_size = block_size; ++ /* Store the alignment offset, to be used when freeing the ++ * allocated block ++ */ ++ real_box->private_offset = private_offset; ++#ifndef G_DISABLE_ASSERT ++ real_box->magic = G_BOX_MAGIC; ++#endif ++ g_ref_count_init (&real_box->ref_count); ++ } ++ ++ TRACE (GLIB_RCBOX_ALLOC (allocated, block_size, atomic, clear)); ++ ++ return allocated + private_size; ++} ++ ++/** ++ * g_rc_box_alloc: ++ * @block_size: the size of the allocation, must be greater than 0 ++ * ++ * Allocates @block_size bytes of memory, and adds reference ++ * counting semantics to it. ++ * ++ * The data will be freed when its reference count drops to ++ * zero. ++ * ++ * The allocated data is guaranteed to be suitably aligned for any ++ * built-in type. ++ * ++ * Returns: (transfer full) (not nullable): a pointer to the allocated memory ++ * ++ * Since: 2.58 ++ */ ++gpointer ++g_rc_box_alloc (gsize block_size) ++{ ++ g_return_val_if_fail (block_size > 0, NULL); ++ ++ return g_rc_box_alloc_full (block_size, STRUCT_ALIGNMENT, FALSE, FALSE); ++} ++ ++/** ++ * g_rc_box_alloc0: ++ * @block_size: the size of the allocation, must be greater than 0 ++ * ++ * Allocates @block_size bytes of memory, and adds reference ++ * counting semantics to it. ++ * ++ * The contents of the returned data is set to zero. ++ * ++ * The data will be freed when its reference count drops to ++ * zero. ++ * ++ * The allocated data is guaranteed to be suitably aligned for any ++ * built-in type. ++ * ++ * Returns: (transfer full) (not nullable): a pointer to the allocated memory ++ * ++ * Since: 2.58 ++ */ ++gpointer ++g_rc_box_alloc0 (gsize block_size) ++{ ++ g_return_val_if_fail (block_size > 0, NULL); ++ ++ return g_rc_box_alloc_full (block_size, STRUCT_ALIGNMENT, FALSE, TRUE); ++} ++ ++/** ++ * g_rc_box_new: ++ * @type: the type to allocate, typically a structure name ++ * ++ * A convenience macro to allocate reference counted data with ++ * the size of the given @type. ++ * ++ * This macro calls g_rc_box_alloc() with `sizeof (@type)` and ++ * casts the returned pointer to a pointer of the given @type, ++ * avoiding a type cast in the source code. ++ * ++ * Returns: (transfer full) (not nullable): a pointer to the ++ * allocated memory, cast to a pointer for the given @type ++ * ++ * Since: 2.58 ++ */ ++ ++/** ++ * g_rc_box_new0: ++ * @type: the type to allocate, typically a structure name ++ * ++ * A convenience macro to allocate reference counted data with ++ * the size of the given @type, and set its contents to zero. ++ * ++ * This macro calls g_rc_box_alloc0() with `sizeof (@type)` and ++ * casts the returned pointer to a pointer of the given @type, ++ * avoiding a type cast in the source code. ++ * ++ * Returns: (transfer full) (not nullable): a pointer to the ++ * allocated memory, cast to a pointer for the given @type ++ * ++ * Since: 2.58 ++ */ ++ ++/** ++ * g_rc_box_dup: ++ * @block_size: the number of bytes to copy, must be greater than 0 ++ * @mem_block: (not nullable): the memory to copy ++ * ++ * Allocates a new block of data with reference counting ++ * semantics, and copies @block_size bytes of @mem_block ++ * into it. ++ * ++ * Returns: (transfer full) (not nullable): a pointer to the allocated ++ * memory ++ * ++ * Since: 2.58 ++ */ ++gpointer ++(g_rc_box_dup) (gsize block_size, ++ gconstpointer mem_block) ++{ ++ gpointer res; ++ ++ g_return_val_if_fail (block_size > 0, NULL); ++ g_return_val_if_fail (mem_block != NULL, NULL); ++ ++ res = g_rc_box_alloc_full (block_size, STRUCT_ALIGNMENT, FALSE, FALSE); ++ memcpy (res, mem_block, block_size); ++ ++ return res; ++} ++ ++/** ++ * g_rc_box_acquire: ++ * @mem_block: (not nullable): a pointer to reference counted data ++ * ++ * Acquires a reference on the data pointed by @mem_block. ++ * ++ * Returns: (transfer full) (not nullable): a pointer to the data, ++ * with its reference count increased ++ * ++ * Since: 2.58 ++ */ ++gpointer ++(g_rc_box_acquire) (gpointer mem_block) ++{ ++ GRcBox *real_box = G_RC_BOX (mem_block); ++ ++ g_return_val_if_fail (mem_block != NULL, NULL); ++#ifndef G_DISABLE_ASSERT ++ g_return_val_if_fail (real_box->magic == G_BOX_MAGIC, NULL); ++#endif ++ ++ g_ref_count_inc (&real_box->ref_count); ++ ++ TRACE (GLIB_RCBOX_ACQUIRE (mem_block, 0)); ++ ++ return mem_block; ++} ++ ++/** ++ * g_rc_box_release: ++ * @mem_block: (transfer full) (not nullable): a pointer to reference counted data ++ * ++ * Releases a reference on the data pointed by @mem_block. ++ * ++ * If the reference was the last one, it will free the ++ * resources allocated for @mem_block. ++ * ++ * Since: 2.58 ++ */ ++void ++g_rc_box_release (gpointer mem_block) ++{ ++ g_rc_box_release_full (mem_block, NULL); ++} ++ ++/** ++ * g_rc_box_release_full: ++ * @mem_block: (transfer full) (not nullable): a pointer to reference counted data ++ * @clear_func: (not nullable): a function to call when clearing the data ++ * ++ * Releases a reference on the data pointed by @mem_block. ++ * ++ * If the reference was the last one, it will call @clear_func ++ * to clear the contents of @mem_block, and then will free the ++ * resources allocated for @mem_block. ++ * ++ * Since: 2.58 ++ */ ++void ++g_rc_box_release_full (gpointer mem_block, ++ GDestroyNotify clear_func) ++{ ++ GRcBox *real_box = G_RC_BOX (mem_block); ++ ++ g_return_if_fail (mem_block != NULL); ++#ifndef G_DISABLE_ASSERT ++ g_return_if_fail (real_box->magic == G_BOX_MAGIC); ++#endif ++ ++ if (g_ref_count_dec (&real_box->ref_count)) ++ { ++ char *real_mem = (char *) real_box - real_box->private_offset; ++ ++ TRACE (GLIB_RCBOX_RELEASE (mem_block, 0)); ++ ++ if (clear_func != NULL) ++ clear_func (mem_block); ++ ++ TRACE (GLIB_RCBOX_FREE (mem_block)); ++ g_free (real_mem); ++ } ++} ++ ++/** ++ * g_rc_box_get_size: ++ * @mem_block: (not nullable): a pointer to reference counted data ++ * ++ * Retrieves the size of the reference counted data pointed by @mem_block. ++ * ++ * Returns: the size of the data, in bytes ++ * ++ * Since: 2.58 ++ */ ++gsize ++g_rc_box_get_size (gpointer mem_block) ++{ ++ GRcBox *real_box = G_RC_BOX (mem_block); ++ ++ g_return_val_if_fail (mem_block != NULL, 0); ++#ifndef G_DISABLE_ASSERT ++ g_return_val_if_fail (real_box->magic == G_BOX_MAGIC, 0); ++#endif ++ ++ return real_box->mem_size; ++} +diff --git a/gi/grcbox.h b/gi/grcbox.h +new file mode 100644 +index 00000000..7c2f89f5 +--- /dev/null ++++ b/gi/grcbox.h +@@ -0,0 +1,96 @@ ++/* grcbox.h: Reference counted data ++ * ++ * Copyright 2018 Emmanuele Bassi ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see . ++ */ ++ ++#pragma once ++ ++#if 0 ++#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) ++#error "Only can be included directly." ++#endif ++ ++#include ++#else ++#include ++ ++#ifndef GLIB_AVAILABLE_IN_2_58 ++#define GLIB_AVAILABLE_IN_2_58 ++#endif ++#endif ++ ++G_BEGIN_DECLS ++ ++GLIB_AVAILABLE_IN_2_58 ++gpointer g_rc_box_alloc (gsize block_size) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1); ++GLIB_AVAILABLE_IN_2_58 ++gpointer g_rc_box_alloc0 (gsize block_size) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1); ++GLIB_AVAILABLE_IN_2_58 ++gpointer g_rc_box_dup (gsize block_size, ++ gconstpointer mem_block) G_GNUC_ALLOC_SIZE(1); ++GLIB_AVAILABLE_IN_2_58 ++gpointer g_rc_box_acquire (gpointer mem_block); ++GLIB_AVAILABLE_IN_2_58 ++void g_rc_box_release (gpointer mem_block); ++GLIB_AVAILABLE_IN_2_58 ++void g_rc_box_release_full (gpointer mem_block, ++ GDestroyNotify clear_func); ++ ++GLIB_AVAILABLE_IN_2_58 ++gsize g_rc_box_get_size (gpointer mem_block); ++ ++GLIB_AVAILABLE_IN_2_58 ++gpointer g_atomic_rc_box_alloc (gsize block_size) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1); ++GLIB_AVAILABLE_IN_2_58 ++gpointer g_atomic_rc_box_alloc0 (gsize block_size) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1); ++GLIB_AVAILABLE_IN_2_58 ++gpointer g_atomic_rc_box_dup (gsize block_size, ++ gconstpointer mem_block) G_GNUC_ALLOC_SIZE(1); ++GLIB_AVAILABLE_IN_2_58 ++gpointer g_atomic_rc_box_acquire (gpointer mem_block); ++GLIB_AVAILABLE_IN_2_58 ++void g_atomic_rc_box_release (gpointer mem_block); ++GLIB_AVAILABLE_IN_2_58 ++void g_atomic_rc_box_release_full (gpointer mem_block, ++ GDestroyNotify clear_func); ++ ++GLIB_AVAILABLE_IN_2_58 ++gsize g_atomic_rc_box_get_size (gpointer mem_block); ++ ++#define g_rc_box_new(type) \ ++ ((type *) g_rc_box_alloc (sizeof (type))) ++#define g_rc_box_new0(type) \ ++ ((type *) g_rc_box_alloc0 (sizeof (type))) ++#define g_atomic_rc_box_new(type) \ ++ ((type *) g_atomic_rc_box_alloc (sizeof (type))) ++#define g_atomic_rc_box_new0(type) \ ++ ((type *) g_atomic_rc_box_alloc0 (sizeof (type))) ++ ++#ifdef g_has_typeof ++/* Type check to avoid assigning references to different types */ ++# define g_rc_box_acquire(mem_block) \ ++ ((__typeof__(mem_block)) (g_rc_box_acquire) (mem_block)) ++# define g_atomic_rc_box_acquire(mem_block) \ ++ ((__typeof__(mem_block)) (g_atomic_rc_box_acquire) (mem_block)) ++ ++/* Type check to avoid duplicating data to different types */ ++# define g_rc_box_dup(block_size,mem_block) \ ++ ((__typeof__(mem_block)) (g_rc_box_dup) (block_size,mem_block)) ++# define g_atomic_rc_box_dup(block_size,mem_block) \ ++ ((__typeof__(mem_block)) (g_atomic_rc_box_dup) (block_size,mem_block)) ++#endif ++ ++G_END_DECLS +diff --git a/gi/grcboxprivate.h b/gi/grcboxprivate.h +new file mode 100644 +index 00000000..7ed94ab8 +--- /dev/null ++++ b/gi/grcboxprivate.h +@@ -0,0 +1,78 @@ ++/* grcboxprivate.h: Reference counted data ++ * ++ * Copyright 2018 Emmanuele Bassi ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see . ++ */ ++ ++#pragma once ++ ++#if 0 ++#include "gtypes.h" ++#else ++#include ++ ++typedef gint grefcount; ++typedef volatile gint gatomicrefcount; ++#endif ++#include "grcbox.h" ++ ++G_BEGIN_DECLS ++ ++typedef struct { ++ grefcount ref_count; ++ ++ gsize mem_size; ++ gsize private_offset; ++ ++#ifndef G_DISABLE_ASSERT ++ /* A "magic" number, used to perform additional integrity ++ * checks on the allocated data ++ */ ++ guint32 magic; ++#endif ++} GRcBox; ++ ++typedef struct { ++ gatomicrefcount ref_count; ++ ++ gsize mem_size; ++ gsize private_offset; ++ ++#ifndef G_DISABLE_ASSERT ++ guint32 magic; ++#endif ++} GArcBox; ++ ++#define G_BOX_MAGIC 0x44ae2bf0 ++ ++/* Keep the two refcounted boxes identical in size */ ++G_STATIC_ASSERT (sizeof (GRcBox) == sizeof (GArcBox)); ++ ++/* This is the default alignment we use when allocating the ++ * refcounted memory blocks; it's similar to the alignment ++ * guaranteed by the malloc() in GNU's libc and by the GSlice ++ * allocator ++ */ ++#define STRUCT_ALIGNMENT (2 * sizeof (gsize)) ++ ++#define G_RC_BOX_SIZE sizeof (GRcBox) ++#define G_ARC_BOX_SIZE sizeof (GArcBox) ++ ++gpointer g_rc_box_alloc_full (gsize block_size, ++ gsize alignment, ++ gboolean atomic, ++ gboolean clear); ++ ++G_END_DECLS +diff --git a/gi/grefcount.c b/gi/grefcount.c +new file mode 100644 +index 00000000..2bc7e9d7 +--- /dev/null ++++ b/gi/grefcount.c +@@ -0,0 +1,289 @@ ++/* grefcount.c: Reference counting ++ * ++ * Copyright 2018 Emmanuele Bassi ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see . ++ */ ++ ++/** ++ * SECTION:refcount ++ * @Title: Reference counting ++ * @Short_description: Reference counting types and functions ++ * ++ * Reference counting is a garbage collection mechanism that is based on ++ * assigning a counter to a data type, or any memory area; the counter is ++ * increased whenever a new reference to that data type is acquired, and ++ * decreased whenever the reference is released. Once the last reference ++ * is released, the resources associated to that data type are freed. ++ * ++ * GLib uses reference counting in many of its data types, and provides ++ * the #grefcount and #gatomicrefcount types to implement safe and atomic ++ * reference counting semantics in new data types. ++ * ++ * It is important to note that #grefcount and #gatomicrefcount should be ++ * considered completely opaque types; you should always use the provided ++ * API to increase and decrease the counters, and you should never check ++ * their content directly, or compare their content with other values. ++ * ++ * Since: 2.58 ++ */ ++ ++#include "config.h" ++ ++#include "grefcount.h" ++ ++#if 0 ++#include "gatomic.h" ++#include "gmessages.h" ++#else ++#include ++#endif ++ ++/** ++ * grefcount: ++ * ++ * A type for implementing non-atomic reference count semantics. ++ * ++ * Use g_ref_count_init() to initialize it; g_ref_count_inc() to ++ * increase the counter, and g_ref_count_dec() to decrease it. ++ * ++ * It is safe to use #grefcount only if you're expecting to operate ++ * on the reference counter from a single thread. It is entirely up ++ * to you to ensure that all reference count changes happen in the ++ * same thread. ++ * ++ * See also: #gatomicrefcount ++ * ++ * Since: 2.58 ++ */ ++ ++/** ++ * gatomicrefcount: ++ * ++ * A type for implementing atomic reference count semantics. ++ * ++ * Use g_atomic_ref_count_init() to initialize it; g_atomic_ref_count_inc() ++ * to increase the counter, and g_atomic_ref_count_dec() to decrease it. ++ * ++ * It is safe to use #gatomicrefcount if you're expecting to operate on the ++ * reference counter from multiple threads. ++ * ++ * See also: #grefcount ++ * ++ * Since: 2.58 ++ */ ++ ++/** ++ * g_ref_count_init: ++ * @rc: the address of a reference count variable ++ * ++ * Initializes a reference count variable. ++ * ++ * Since: 2.58 ++ */ ++void ++(g_ref_count_init) (grefcount *rc) ++{ ++ g_return_if_fail (rc != NULL); ++ ++ /* Non-atomic refcounting is implemented using the negative range ++ * of signed integers: ++ * ++ * G_MININT Z¯< 0 > Z⁺ G_MAXINT ++ * |----------------------------|----------------------------| ++ * ++ * Acquiring a reference moves us towards MININT, and releasing a ++ * reference moves us towards 0. ++ */ ++ *rc = -1; ++} ++ ++/** ++ * g_ref_count_inc: ++ * @rc: the address of a reference count variable ++ * ++ * Increases the reference count. ++ * ++ * Since: 2.58 ++ */ ++void ++(g_ref_count_inc) (grefcount *rc) ++{ ++ grefcount rrc; ++ ++ g_return_if_fail (rc != NULL); ++ ++ rrc = *rc; ++ ++ g_return_if_fail (rrc < 0); ++ ++ /* Check for saturation */ ++ if (rrc == G_MININT) ++ { ++ g_critical ("Reference count %p has reached saturation", rc); ++ return; ++ } ++ ++ rrc -= 1; ++ ++ *rc = rrc; ++} ++ ++/** ++ * g_ref_count_dec: ++ * @rc: the address of a reference count variable ++ * ++ * Decreases the reference count. ++ * ++ * Returns: %TRUE if the reference count reached 0, and %FALSE otherwise ++ * ++ * Since: 2.58 ++ */ ++gboolean ++(g_ref_count_dec) (grefcount *rc) ++{ ++ grefcount rrc; ++ ++ g_return_val_if_fail (rc != NULL, FALSE); ++ ++ rrc = *rc; ++ ++ g_return_val_if_fail (rrc < 0, FALSE); ++ ++ rrc += 1; ++ if (rrc == 0) ++ return TRUE; ++ ++ *rc = rrc; ++ ++ return FALSE; ++} ++ ++/** ++ * g_ref_count_compare: ++ * @rc: the address of a reference count variable ++ * @val: the value to compare ++ * ++ * Compares the current value of @rc with @val. ++ * ++ * Returns: %TRUE if the reference count is the same ++ * as the given value ++ * ++ * Since: 2.58 ++ */ ++gboolean ++(g_ref_count_compare) (grefcount *rc, ++ gint val) ++{ ++ grefcount rrc; ++ ++ g_return_val_if_fail (rc != NULL, FALSE); ++ g_return_val_if_fail (val >= 0, FALSE); ++ ++ rrc = *rc; ++ ++ if (val == G_MAXINT) ++ return rrc == G_MININT; ++ ++ return rrc == -val; ++} ++ ++/** ++ * g_atomic_ref_count_init: ++ * @arc: the address of an atomic reference count variable ++ * ++ * Initializes a reference count variable. ++ * ++ * Since: 2.58 ++ */ ++void ++(g_atomic_ref_count_init) (gatomicrefcount *arc) ++{ ++ g_return_if_fail (arc != NULL); ++ ++ /* Atomic refcounting is implemented using the positive range ++ * of signed integers: ++ * ++ * G_MININT Z¯< 0 > Z⁺ G_MAXINT ++ * |----------------------------|----------------------------| ++ * ++ * Acquiring a reference moves us towards MAXINT, and releasing a ++ * reference moves us towards 0. ++ */ ++ *arc = 1; ++} ++ ++/** ++ * g_atomic_ref_count_inc: ++ * @arc: the address of an atomic reference count variable ++ * ++ * Atomically increases the reference count. ++ * ++ * Since: 2.58 ++ */ ++void ++(g_atomic_ref_count_inc) (gatomicrefcount *arc) ++{ ++ g_return_if_fail (arc != NULL); ++ g_return_if_fail (g_atomic_int_get (arc) > 0); ++ ++ if (g_atomic_int_get (arc) == G_MAXINT) ++ { ++ g_critical ("Reference count has reached saturation"); ++ return; ++ } ++ ++ g_atomic_int_inc (arc); ++} ++ ++/** ++ * g_atomic_ref_count_dec: ++ * @arc: the address of an atomic reference count variable ++ * ++ * Atomically decreases the reference count. ++ * ++ * Returns: %TRUE if the reference count reached 0, and %FALSE otherwise ++ * ++ * Since: 2.58 ++ */ ++gboolean ++(g_atomic_ref_count_dec) (gatomicrefcount *arc) ++{ ++ g_return_val_if_fail (arc != NULL, FALSE); ++ g_return_val_if_fail (g_atomic_int_get (arc) > 0, FALSE); ++ ++ return g_atomic_int_dec_and_test (arc); ++} ++ ++/** ++ * g_atomic_ref_count_compare: ++ * @arc: the address of an atomic reference count variable ++ * @val: the value to compare ++ * ++ * Atomically compares the current value of @arc with @val. ++ * ++ * Returns: %TRUE if the reference count is the same ++ * as the given value ++ * ++ * Since: 2.58 ++ */ ++gboolean ++(g_atomic_ref_count_compare) (gatomicrefcount *arc, ++ gint val) ++{ ++ g_return_val_if_fail (arc != NULL, FALSE); ++ g_return_val_if_fail (val >= 0, FALSE); ++ ++ return g_atomic_int_get (arc) == val; ++} +diff --git a/gi/grefcount.h b/gi/grefcount.h +new file mode 100644 +index 00000000..d2f78037 +--- /dev/null ++++ b/gi/grefcount.h +@@ -0,0 +1,134 @@ ++/* grefcount.h: Reference counting ++ * ++ * Copyright 2018 Emmanuele Bassi ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see . ++ */ ++ ++#ifndef __GREFCOUNT_H__ ++#define __GREFCOUNT_H__ ++ ++#if 0 ++#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) ++#error "Only can be included directly." ++#endif ++ ++#include ++#include ++#else ++#include ++ ++#ifndef GLIB_AVAILABLE_IN_2_58 ++#define GLIB_AVAILABLE_IN_2_58 ++#endif ++ ++typedef gint grefcount; ++typedef volatile gint gatomicrefcount; ++#endif ++ ++G_BEGIN_DECLS ++ ++GLIB_AVAILABLE_IN_2_58 ++void g_ref_count_init (grefcount *rc); ++GLIB_AVAILABLE_IN_2_58 ++void g_ref_count_inc (grefcount *rc); ++GLIB_AVAILABLE_IN_2_58 ++gboolean g_ref_count_dec (grefcount *rc); ++GLIB_AVAILABLE_IN_2_58 ++gboolean g_ref_count_compare (grefcount *rc, ++ gint val); ++ ++GLIB_AVAILABLE_IN_2_58 ++void g_atomic_ref_count_init (gatomicrefcount *arc); ++GLIB_AVAILABLE_IN_2_58 ++void g_atomic_ref_count_inc (gatomicrefcount *arc); ++GLIB_AVAILABLE_IN_2_58 ++gboolean g_atomic_ref_count_dec (gatomicrefcount *arc); ++GLIB_AVAILABLE_IN_2_58 ++gboolean g_atomic_ref_count_compare (gatomicrefcount *arc, ++ gint val); ++ ++/* On GCC we can use __extension__ to inline the API without using ++ * ancillary functions; we only do this when disabling checks, as ++ * it disables warnings when saturating the reference counters ++ */ ++#if defined(__GNUC__) && defined(G_DISABLE_CHECKS) ++ ++# define g_ref_count_init(rc) \ ++ (G_GNUC_EXTENSION ({ \ ++ G_STATIC_ASSERT (sizeof *(rc) == sizeof (grefcount)); \ ++ (void) (0 ? *(rc) ^ *(rc) : 1); \ ++ *(rc) = -1; \ ++ })) ++ ++# define g_ref_count_inc(rc) \ ++ (G_GNUC_EXTENSION ({ \ ++ G_STATIC_ASSERT (sizeof *(rc) == sizeof (grefcount)); \ ++ (void) (0 ? *(rc) ^ *(rc) : 1); \ ++ if (*(rc) == G_MININT) ; else { \ ++ *(rc) -= 1; \ ++ } \ ++ })) ++ ++# define g_ref_count_dec(rc) \ ++ (G_GNUC_EXTENSION ({ \ ++ G_STATIC_ASSERT (sizeof *(rc) == sizeof (grefcount)); \ ++ grefcount __rc = *(rc); \ ++ __rc += 1; \ ++ if (__rc == 0) ; else { \ ++ *(rc) = __rc; \ ++ } \ ++ (gboolean) (__rc == 0); \ ++ })) ++ ++# define g_ref_count_compare(rc,val) \ ++ (G_GNUC_EXTENSION ({ \ ++ G_STATIC_ASSERT (sizeof *(rc) == sizeof (grefcount)); \ ++ (void) (0 ? *(rc) ^ (val) : 1); \ ++ (gboolean) (*(rc) == -(val)); \ ++ })) ++ ++# define g_atomic_ref_count_init(rc) \ ++ (G_GNUC_EXTENSION ({ \ ++ G_STATIC_ASSERT (sizeof *(rc) == sizeof (gatomicrefcount)); \ ++ (void) (0 ? *(rc) ^ *(rc) : 1); \ ++ *(rc) = 1; \ ++ })) ++ ++# define g_atomic_ref_count_inc(rc) \ ++ (G_GNUC_EXTENSION ({ \ ++ G_STATIC_ASSERT (sizeof *(rc) == sizeof (gatomicrefcount)); \ ++ (void) (0 ? *(rc) ^ *(rc) : 1); \ ++ (void) (g_atomic_int_get (rc) == G_MAXINT ? 0 : g_atomic_int_inc ((rc))); \ ++ })) ++ ++# define g_atomic_ref_count_dec(rc) \ ++ (G_GNUC_EXTENSION ({ \ ++ G_STATIC_ASSERT (sizeof *(rc) == sizeof (gatomicrefcount)); \ ++ (void) (0 ? *(rc) ^ *(rc) : 1); \ ++ g_atomic_int_dec_and_test ((rc)); \ ++ })) ++ ++# define g_atomic_ref_count_compare(rc,val) \ ++ (G_GNUC_EXTENSION ({ \ ++ G_STATIC_ASSERT (sizeof *(rc) == sizeof (gatomicrefcount)); \ ++ (void) (0 ? *(rc) ^ (val) : 1); \ ++ (gboolean) (g_atomic_int_get (rc) == (val)); \ ++ })) ++ ++#endif /* __GNUC__ && G_DISABLE_CHECKS */ ++ ++G_END_DECLS ++ ++#endif /* __GREFCOUNT_H__ */ +diff --git a/gi/wrapperutils.h b/gi/wrapperutils.h +index 5fa4ae2f..4a67ea87 100644 +--- a/gi/wrapperutils.h ++++ b/gi/wrapperutils.h +@@ -31,6 +31,8 @@ + #include "gjs/macros.h" + #include "util/log.h" + ++#include "gi/grcbox.h" ++ + G_BEGIN_DECLS + + GJS_JSAPI_RETURN_CONVENTION +diff --git a/gjs-srcs.mk b/gjs-srcs.mk +index dcdc4387..a66f4788 100644 +--- a/gjs-srcs.mk ++++ b/gjs-srcs.mk +@@ -13,6 +13,12 @@ gjs_public_headers = \ + # public + + gjs_srcs = \ ++ gi/garcbox.c \ ++ gi/grcbox.c \ ++ gi/grcbox.h \ ++ gi/grcboxprivate.h \ ++ gi/grefcount.c \ ++ gi/grefcount.h \ + gi/arg.cpp \ + gi/arg.h \ + gi/boxed.cpp \ +-- +2.21.0 + diff --git a/SPECS/gjs.spec b/SPECS/gjs.spec index 6bd2a58..5f0595f 100644 --- a/SPECS/gjs.spec +++ b/SPECS/gjs.spec @@ -1,10 +1,11 @@ -%global glib2_version 2.50.0 +%global glib2_version 2.54.0 %global gobject_introspection_version 1.41.4 %global gtk3_version 3.20 +%global mozjs60_version 60.9.0 Name: gjs -Version: 1.52.5 -Release: 2%{?dist} +Version: 1.56.2 +Release: 3%{?dist} Summary: Javascript Bindings for GNOME # The following files contain code from Mozilla which @@ -13,24 +14,27 @@ Summary: Javascript Bindings for GNOME # Stack printer (gjs/stack.c) License: MIT and (MPLv1.1 or GPLv2+ or LGPLv2+) URL: https://wiki.gnome.org/Projects/Gjs -Source0: https://download.gnome.org/sources/%{name}/1.52/%{name}-%{version}.tar.xz +Source0: https://download.gnome.org/sources/%{name}/1.56/%{name}-%{version}.tar.xz -Patch0: 0001-cairo-context-Special-case-0-sized-vector.patch +Patch0: 0001-gi-Include-missing-glib-bits.patch BuildRequires: cairo-gobject-devel BuildRequires: chrpath -BuildRequires: gobject-introspection-devel >= %{gobject_introspection_version} -BuildRequires: readline-devel +BuildRequires: dbus-daemon BuildRequires: dbus-glib-devel +BuildRequires: gcc-c++ BuildRequires: gettext BuildRequires: glib2-devel >= %{glib2_version} +BuildRequires: gobject-introspection-devel >= %{gobject_introspection_version} BuildRequires: gtk3-devel >= %{gtk3_version} -BuildRequires: mozjs52-devel +BuildRequires: mozjs60-devel >= %{mozjs60_version} BuildRequires: pkgconfig +BuildRequires: readline-devel Requires: glib2%{?_isa} >= %{glib2_version} Requires: gobject-introspection%{?_isa} >= %{gobject_introspection_version} Requires: gtk3%{?_isa} >= %{gtk3_version} +Requires: mozjs60%{?_isa} >= %{mozjs60_version} # Filter provides for private libraries %global __provides_exclude_from ^%{_libdir}/gjs/ @@ -97,6 +101,14 @@ find %{buildroot} -name '*.la' -exec rm -f {} ';' %{_datadir}/installed-tests %changelog +* Tue Sep 10 2019 Kalev Lember - 1.56.2-3 +- Rebuild for mozjs60 s390x fixes +- Related: #1746889 + +* Thu May 23 2019 Florian Müllner - 1.56.2-1 +- Update to 1.56.2 + Resolves: #1698923 + * Fri Feb 22 2019 Florian Müllner - 1.52.5-2 - Fix crash in cairo support module Resolves: #1678869