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 <glib__private__@plt>
   11322:       8b 35 0c b2 05 00       mov    0x5b20c(%rip),%esi        # 6c534 <quark_weak_locations.lto_priv.0>
   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 <weak_ref_data_get_or_create_cb.lto_priv.0>
   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 <weak_ref_data_get_or_create_cb.lto_priv.0>
   1132b:       8b 35 0b b2 05 00       mov    0x5b20b(%rip),%esi        # 6c53c <quark_weak_locations.lto_priv.0>
   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).
This commit is contained in:
Thomas Haller 2024-03-04 20:46:43 +01:00
parent 7436b8056d
commit 482e078083

View File

@ -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;