mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-12 07:26:15 +01:00
Use the GObject hole on 64bit arches for some flags to improve performance
This uses a 32bit hole in the GObject structure on 64bit arches as a flag field which can be optionally used for some preformance hints. Currently there is a flag that gets set any time you connect to a signal on a GObject which is used as early bailout for signal emissions, and using the flags field instead of a user-data for checking if a GObject is under construction.
This commit is contained in:
parent
cf990faae5
commit
5afd574e91
@ -162,6 +162,29 @@ enum {
|
||||
PROP_NONE
|
||||
};
|
||||
|
||||
#define OPTIONAL_FLAG_IN_CONSTRUCTION 1<<0
|
||||
#define OPTIONAL_FLAG_HAS_SIGNAL_HANDLER 1<<1 /* Set if object ever had a signal handler */
|
||||
|
||||
#if SIZEOF_INT == 4 && GLIB_SIZEOF_VOID_P == 8
|
||||
#define HAVE_OPTIONAL_FLAGS
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GTypeInstance g_type_instance;
|
||||
|
||||
/*< private >*/
|
||||
volatile guint ref_count;
|
||||
#ifdef HAVE_OPTIONAL_FLAGS
|
||||
volatile guint optional_flags;
|
||||
#endif
|
||||
GData *qdata;
|
||||
} GObjectReal;
|
||||
|
||||
G_STATIC_ASSERT(sizeof(GObject) == sizeof(GObjectReal));
|
||||
G_STATIC_ASSERT(G_STRUCT_OFFSET(GObject, ref_count) == G_STRUCT_OFFSET(GObjectReal, ref_count));
|
||||
G_STATIC_ASSERT(G_STRUCT_OFFSET(GObject, qdata) == G_STRUCT_OFFSET(GObjectReal, qdata));
|
||||
|
||||
|
||||
/* --- prototypes --- */
|
||||
static void g_object_base_class_init (GObjectClass *class);
|
||||
@ -1008,10 +1031,83 @@ g_object_interface_list_properties (gpointer g_iface,
|
||||
return pspecs;
|
||||
}
|
||||
|
||||
static inline guint
|
||||
object_get_optional_flags (GObject *object)
|
||||
{
|
||||
#ifdef HAVE_OPTIONAL_FLAGS
|
||||
GObjectReal *real = (GObjectReal *)object;
|
||||
return (guint)g_atomic_int_get (&real->optional_flags);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void
|
||||
object_set_optional_flags (GObject *object,
|
||||
guint flags)
|
||||
{
|
||||
#ifdef HAVE_OPTIONAL_FLAGS
|
||||
GObjectReal *real = (GObjectReal *)object;
|
||||
g_atomic_int_or (&real->optional_flags, flags);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void
|
||||
object_unset_optional_flags (GObject *object,
|
||||
guint flags)
|
||||
{
|
||||
#ifdef HAVE_OPTIONAL_FLAGS
|
||||
GObjectReal *real = (GObjectReal *)object;
|
||||
g_atomic_int_and (&real->optional_flags, ~flags);
|
||||
#endif
|
||||
}
|
||||
|
||||
gboolean
|
||||
_g_object_has_signal_handler (GObject *object)
|
||||
{
|
||||
#ifdef HAVE_OPTIONAL_FLAGS
|
||||
return (object_get_optional_flags (object) & OPTIONAL_FLAG_HAS_SIGNAL_HANDLER) != 0;
|
||||
#else
|
||||
return TRUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
_g_object_set_has_signal_handler (GObject *object)
|
||||
{
|
||||
#ifdef HAVE_OPTIONAL_FLAGS
|
||||
object_set_optional_flags (object, OPTIONAL_FLAG_HAS_SIGNAL_HANDLER);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
object_in_construction (GObject *object)
|
||||
{
|
||||
#ifdef HAVE_OPTIONAL_FLAGS
|
||||
return (object_get_optional_flags (object) & OPTIONAL_FLAG_IN_CONSTRUCTION) != 0;
|
||||
#else
|
||||
return g_datalist_id_get_data (&object->qdata, quark_in_construction) != NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void
|
||||
set_object_in_construction (GObject *object)
|
||||
{
|
||||
#ifdef HAVE_OPTIONAL_FLAGS
|
||||
object_set_optional_flags (object, OPTIONAL_FLAG_IN_CONSTRUCTION);
|
||||
#else
|
||||
g_datalist_id_set_data (&object->qdata, quark_in_construction, object);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void
|
||||
unset_object_in_construction (GObject *object)
|
||||
{
|
||||
#ifdef HAVE_OPTIONAL_FLAGS
|
||||
object_unset_optional_flags (object, OPTIONAL_FLAG_IN_CONSTRUCTION);
|
||||
#else
|
||||
g_datalist_id_set_data (&object->qdata, quark_in_construction, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1030,7 +1126,7 @@ g_object_init (GObject *object,
|
||||
if (CLASS_HAS_CUSTOM_CONSTRUCTOR (class))
|
||||
{
|
||||
/* mark object in-construction for notify_queue_thaw() and to allow construct-only properties */
|
||||
g_datalist_id_set_data (&object->qdata, quark_in_construction, object);
|
||||
set_object_in_construction (object);
|
||||
}
|
||||
|
||||
GOBJECT_IF_DEBUG (OBJECTS,
|
||||
@ -1766,7 +1862,7 @@ g_object_new_with_custom_constructor (GObjectClass *class,
|
||||
*/
|
||||
newly_constructed = object_in_construction (object);
|
||||
if (newly_constructed)
|
||||
g_datalist_id_set_data (&object->qdata, quark_in_construction, NULL);
|
||||
unset_object_in_construction (object);
|
||||
|
||||
if (CLASS_HAS_PROPS (class))
|
||||
{
|
||||
|
@ -711,7 +711,7 @@ handler_insert (guint signal_id,
|
||||
HandlerList *hlist;
|
||||
|
||||
g_assert (handler->prev == NULL && handler->next == NULL); /* paranoid */
|
||||
|
||||
|
||||
hlist = handler_list_ensure (signal_id, instance);
|
||||
if (!hlist->handlers)
|
||||
{
|
||||
@ -2345,7 +2345,10 @@ g_signal_connect_closure_by_id (gpointer instance,
|
||||
else
|
||||
{
|
||||
Handler *handler = handler_new (signal_id, instance, after);
|
||||
|
||||
|
||||
if (G_TYPE_IS_OBJECT (node->itype))
|
||||
_g_object_set_has_signal_handler ((GObject *)instance);
|
||||
|
||||
handler_seq_no = handler->sequential_number;
|
||||
handler->detail = detail;
|
||||
handler->closure = g_closure_ref (closure);
|
||||
@ -2410,6 +2413,9 @@ g_signal_connect_closure (gpointer instance,
|
||||
{
|
||||
Handler *handler = handler_new (signal_id, instance, after);
|
||||
|
||||
if (G_TYPE_IS_OBJECT (node->itype))
|
||||
_g_object_set_has_signal_handler ((GObject *)instance);
|
||||
|
||||
handler_seq_no = handler->sequential_number;
|
||||
handler->detail = detail;
|
||||
handler->closure = g_closure_ref (closure);
|
||||
@ -2511,6 +2517,9 @@ g_signal_connect_data (gpointer instance,
|
||||
{
|
||||
Handler *handler = handler_new (signal_id, instance, after);
|
||||
|
||||
if (G_TYPE_IS_OBJECT (node->itype))
|
||||
_g_object_set_has_signal_handler ((GObject *)instance);
|
||||
|
||||
handler_seq_no = handler->sequential_number;
|
||||
handler->detail = detail;
|
||||
handler->closure = g_closure_ref ((swapped ? g_cclosure_new_swap : g_cclosure_new) (c_handler, data, destroy_data));
|
||||
@ -3121,7 +3130,14 @@ g_signal_emitv (const GValue *instance_and_params,
|
||||
(node->single_va_closure == SINGLE_VA_CLOSURE_EMPTY_MAGIC ||
|
||||
_g_closure_is_void (node->single_va_closure, instance)))
|
||||
{
|
||||
HandlerList* hlist = handler_list_lookup (node->signal_id, instance);
|
||||
HandlerList* hlist;
|
||||
|
||||
/* single_va_closure is only true for GObjects, so fast path if no handler ever connected to the signal */
|
||||
if (_g_object_has_signal_handler ((GObject *)instance))
|
||||
hlist = handler_list_lookup (node->signal_id, instance);
|
||||
else
|
||||
hlist = NULL;
|
||||
|
||||
if (hlist == NULL || hlist->handlers == NULL)
|
||||
{
|
||||
/* nothing to do to emit this signal */
|
||||
@ -3204,7 +3220,7 @@ g_signal_emit_valist (gpointer instance,
|
||||
|
||||
if (node->single_va_closure != NULL)
|
||||
{
|
||||
HandlerList* hlist = handler_list_lookup (node->signal_id, instance);
|
||||
HandlerList* hlist;
|
||||
Handler *fastpath_handler = NULL;
|
||||
Handler *l;
|
||||
GClosure *closure = NULL;
|
||||
@ -3226,6 +3242,12 @@ g_signal_emit_valist (gpointer instance,
|
||||
fastpath = FALSE;
|
||||
}
|
||||
|
||||
/* single_va_closure is only true for GObjects, so fast path if no handler ever connected to the signal */
|
||||
if (_g_object_has_signal_handler ((GObject *)instance))
|
||||
hlist = handler_list_lookup (node->signal_id, instance);
|
||||
else
|
||||
hlist = NULL;
|
||||
|
||||
for (l = hlist ? hlist->handlers : NULL; fastpath && l != NULL; l = l->next)
|
||||
{
|
||||
if (!l->block_count &&
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
#include "gboxed.h"
|
||||
#include "gclosure.h"
|
||||
#include "gobject.h"
|
||||
|
||||
/*< private >
|
||||
* GOBJECT_IF_DEBUG:
|
||||
@ -92,6 +93,9 @@ void _g_closure_invoke_va (GClosure *closure,
|
||||
int n_params,
|
||||
GType *param_types);
|
||||
|
||||
gboolean _g_object_has_signal_handler (GObject *object);
|
||||
void _g_object_set_has_signal_handler (GObject *object);
|
||||
|
||||
/**
|
||||
* _G_DEFINE_TYPE_EXTENDED_WITH_PRELUDE:
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user