From 482e0780837c39027dca219a4dcda40ed545f350 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 4 Mar 2024 20:46:43 +0100 Subject: [PATCH] gobject: avoid GLIB_PRIVATE_CALL() for g_datalist_id_update_atomic() Cache the function pointer for g_datalist_id_update_atomic() in a static variable in "gobject.c" to avoid looking it up repeatedly. g_datalist_id_update_atomic() is anyway internal API. Like GData is not a useful data structure in general, this function is only useful for something specific inside GObject. It can be easily seen that _local_g_datalist_id_update_atomic is never read without having a GObject at hand (because we call it on `&object->qdata`). Thus initializing the pointer in g_object_do_class_init() (under lock) is sufficient to ensure thread-safe initialization. Note that we still set the pointer via g_atomic_pointer_set(). This is done in an attempt to pacify thread sanatizer. Note that also with LTO enabled, the GLIB_PRIVATE_CALL() call cannot be inlined. Previously we get: 0000000000011300 <_weak_ref_set>: ... 1131d: e8 ee 03 ff ff call 1710 11322: 8b 35 0c b2 05 00 mov 0x5b20c(%rip),%esi # 6c534 11328: 4c 89 e1 mov %r12,%rcx 1132b: 49 8d 7c 24 10 lea 0x10(%r12),%rdi 11330: 48 8d 15 b9 42 ff ff lea -0xbd47(%rip),%rdx # 55f0 11337: ff 90 80 00 00 00 call *0x80(%rax) afterwards: 0000000000011300 <_weak_ref_set>: ... 1131d: 48 8d 7e 10 lea 0x10(%rsi),%rdi 11321: 48 89 f1 mov %rsi,%rcx 11324: 48 8d 15 c5 42 ff ff lea -0xbd3b(%rip),%rdx # 55f0 1132b: 8b 35 0b b2 05 00 mov 0x5b20b(%rip),%esi # 6c53c 11331: ff 15 f9 b1 05 00 call *0x5b1f9(%rip) # 6c530 <_local_g_datalist_id_update_atomic.lto_priv.0> Also note, that the point here is not to optimize _weak_ref_set() (which is not a hot path). There is work in progress that will use g_datalist_id_update_atomic() for more purposes (and during more relevant code paths of GObject). --- gobject/gobject.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/gobject/gobject.c b/gobject/gobject.c index f73f3bf30..50d929ba4 100644 --- a/gobject/gobject.c +++ b/gobject/gobject.c @@ -233,6 +233,13 @@ static gulong gobject_signals[LAST_SIGNAL] = { 0, }; static guint (*floating_flag_handler) (GObject*, gint) = object_floating_flag_handler; static GQuark quark_weak_locations = 0; +static gpointer (*_local_g_datalist_id_update_atomic) (GData **datalist, + GQuark key_id, + GDataListUpdateAtomicFunc callback, + gpointer user_data) = NULL; +#undef _g_datalist_id_update_atomic +#define _g_datalist_id_update_atomic(...) ((_local_g_datalist_id_update_atomic) (__VA_ARGS__)) + #if HAVE_PRIVATE G_ALWAYS_INLINE static inline GObjectPrivate * g_object_get_instance_private (GObject *object) @@ -980,6 +987,8 @@ g_object_do_class_init (GObjectClass *class) quark_toggle_refs = g_quark_from_static_string ("GObject-toggle-references"); quark_notify_queue = g_quark_from_static_string ("GObject-notify-queue"); + g_atomic_pointer_set (&_local_g_datalist_id_update_atomic, GLIB_PRIVATE_CALL (g_datalist_id_update_atomic)); + g_object_init_pspec_pool (); class->constructor = g_object_constructor;