mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-24 03:02:10 +01:00
gtype: improve get_type fast path
The -fstack-protector-strong used in many distributions by default has a rather drastic slowdown of the fast path in generated _get_type() functions using G_DEFINE_* macros. The amount can vary by architecture, GCC version, and compiler flags. To work around this, and ensure a higher probability that our fast-path will match what we had previously, we need to break out the slow-path (registering the type) into a secondary function that is not a candidate for inlining. This ensures that the common case (type registered, return the GType id) is the hot path and handled in the prologue of the generated assembly even when -fstack-protector-strong is enabled. https://bugzilla.gnome.org/show_bug.cgi?id=795180
This commit is contained in:
parent
ede5c3f8d9
commit
e924f77736
109
gobject/gtype.h
109
gobject/gtype.h
@ -1948,6 +1948,7 @@ static void type_name##_class_intern_init (gpointer klass) \
|
|||||||
\
|
\
|
||||||
static void type_name##_init (TypeName *self); \
|
static void type_name##_init (TypeName *self); \
|
||||||
static void type_name##_class_init (TypeName##Class *klass); \
|
static void type_name##_class_init (TypeName##Class *klass); \
|
||||||
|
static GType type_name##_get_type_once (void); \
|
||||||
static gpointer type_name##_parent_class = NULL; \
|
static gpointer type_name##_parent_class = NULL; \
|
||||||
static gint TypeName##_private_offset; \
|
static gint TypeName##_private_offset; \
|
||||||
\
|
\
|
||||||
@ -1970,7 +1971,17 @@ type_name##_get_type (void) \
|
|||||||
#define _G_DEFINE_TYPE_EXTENDED_BEGIN_REGISTER(TypeName, type_name, TYPE_PARENT, flags) \
|
#define _G_DEFINE_TYPE_EXTENDED_BEGIN_REGISTER(TypeName, type_name, TYPE_PARENT, flags) \
|
||||||
if (g_once_init_enter (&g_define_type_id__volatile)) \
|
if (g_once_init_enter (&g_define_type_id__volatile)) \
|
||||||
{ \
|
{ \
|
||||||
GType g_define_type_id = \
|
GType g_define_type_id = type_name##_get_type_once (); \
|
||||||
|
g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); \
|
||||||
|
} \
|
||||||
|
return g_define_type_id__volatile; \
|
||||||
|
} /* closes type_name##_get_type() */ \
|
||||||
|
\
|
||||||
|
G_GNUC_NO_INLINE \
|
||||||
|
static GType \
|
||||||
|
type_name##_get_type_once (void) \
|
||||||
|
{ \
|
||||||
|
GType g_define_type_id = \
|
||||||
g_type_register_static_simple (TYPE_PARENT, \
|
g_type_register_static_simple (TYPE_PARENT, \
|
||||||
g_intern_static_string (#TypeName), \
|
g_intern_static_string (#TypeName), \
|
||||||
sizeof (TypeName##Class), \
|
sizeof (TypeName##Class), \
|
||||||
@ -1978,14 +1989,12 @@ type_name##_get_type (void) \
|
|||||||
sizeof (TypeName), \
|
sizeof (TypeName), \
|
||||||
(GInstanceInitFunc)(void (*)(void)) type_name##_init, \
|
(GInstanceInitFunc)(void (*)(void)) type_name##_init, \
|
||||||
(GTypeFlags) flags); \
|
(GTypeFlags) flags); \
|
||||||
{ /* custom code follows */
|
{ /* custom code follows */
|
||||||
#define _G_DEFINE_TYPE_EXTENDED_END() \
|
#define _G_DEFINE_TYPE_EXTENDED_END() \
|
||||||
/* following custom code */ \
|
/* following custom code */ \
|
||||||
} \
|
|
||||||
g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); \
|
|
||||||
} \
|
} \
|
||||||
return g_define_type_id__volatile; \
|
return g_define_type_id; \
|
||||||
} /* closes type_name##_get_type() */
|
} /* closes type_name##_get_type_once() */
|
||||||
|
|
||||||
/* This was defined before we had G_DEFINE_TYPE_WITH_CODE_AND_PRELUDE, it's simplest
|
/* This was defined before we had G_DEFINE_TYPE_WITH_CODE_AND_PRELUDE, it's simplest
|
||||||
* to keep it.
|
* to keep it.
|
||||||
@ -2070,42 +2079,66 @@ type_name##_get_type (void) \
|
|||||||
*/
|
*/
|
||||||
#if !defined (__cplusplus) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)) && !(defined (__APPLE__) && defined (__ppc64__))
|
#if !defined (__cplusplus) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)) && !(defined (__APPLE__) && defined (__ppc64__))
|
||||||
#define _G_DEFINE_BOXED_TYPE_BEGIN(TypeName, type_name, copy_func, free_func) \
|
#define _G_DEFINE_BOXED_TYPE_BEGIN(TypeName, type_name, copy_func, free_func) \
|
||||||
|
static GType type_name##_get_type_once (void); \
|
||||||
|
\
|
||||||
GType \
|
GType \
|
||||||
type_name##_get_type (void) \
|
type_name##_get_type (void) \
|
||||||
{ \
|
{ \
|
||||||
static volatile gsize g_define_type_id__volatile = 0; \
|
static volatile gsize g_define_type_id__volatile = 0; \
|
||||||
if (g_once_init_enter (&g_define_type_id__volatile)) \
|
if (g_once_init_enter (&g_define_type_id__volatile)) \
|
||||||
{ \
|
{ \
|
||||||
GType (* _g_register_boxed) \
|
GType g_define_type_id = type_name##_get_type_once (); \
|
||||||
(const gchar *, \
|
g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); \
|
||||||
union \
|
} \
|
||||||
{ \
|
return g_define_type_id__volatile; \
|
||||||
TypeName * (*do_copy_type) (TypeName *); \
|
} \
|
||||||
TypeName * (*do_const_copy_type) (const TypeName *); \
|
\
|
||||||
GBoxedCopyFunc do_copy_boxed; \
|
G_GNUC_NO_INLINE \
|
||||||
} __attribute__((__transparent_union__)), \
|
static GType \
|
||||||
union \
|
type_name##_get_type_once (void) \
|
||||||
{ \
|
{ \
|
||||||
void (* do_free_type) (TypeName *); \
|
GType (* _g_register_boxed) \
|
||||||
GBoxedFreeFunc do_free_boxed; \
|
(const gchar *, \
|
||||||
} __attribute__((__transparent_union__)) \
|
union \
|
||||||
) = g_boxed_type_register_static; \
|
{ \
|
||||||
GType g_define_type_id = \
|
TypeName * (*do_copy_type) (TypeName *); \
|
||||||
_g_register_boxed (g_intern_static_string (#TypeName), copy_func, free_func); \
|
TypeName * (*do_const_copy_type) (const TypeName *); \
|
||||||
{ /* custom code follows */
|
GBoxedCopyFunc do_copy_boxed; \
|
||||||
|
} __attribute__((__transparent_union__)), \
|
||||||
|
union \
|
||||||
|
{ \
|
||||||
|
void (* do_free_type) (TypeName *); \
|
||||||
|
GBoxedFreeFunc do_free_boxed; \
|
||||||
|
} __attribute__((__transparent_union__)) \
|
||||||
|
) = g_boxed_type_register_static; \
|
||||||
|
GType g_define_type_id = \
|
||||||
|
_g_register_boxed (g_intern_static_string (#TypeName), copy_func, free_func); \
|
||||||
|
{ /* custom code follows */
|
||||||
#else
|
#else
|
||||||
#define _G_DEFINE_BOXED_TYPE_BEGIN(TypeName, type_name, copy_func, free_func) \
|
#define _G_DEFINE_BOXED_TYPE_BEGIN(TypeName, type_name, copy_func, free_func) \
|
||||||
|
static GType type_name##_get_type_once (void); \
|
||||||
|
\
|
||||||
GType \
|
GType \
|
||||||
type_name##_get_type (void) \
|
type_name##_get_type (void) \
|
||||||
{ \
|
{ \
|
||||||
static volatile gsize g_define_type_id__volatile = 0; \
|
static volatile gsize g_define_type_id__volatile = 0; \
|
||||||
if (g_once_init_enter (&g_define_type_id__volatile)) \
|
if (g_once_init_enter (&g_define_type_id__volatile)) \
|
||||||
{ \
|
{ \
|
||||||
GType g_define_type_id = \
|
GType g_define_type_id = type_name##_get_type_once (); \
|
||||||
g_boxed_type_register_static (g_intern_static_string (#TypeName), \
|
g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); \
|
||||||
(GBoxedCopyFunc) copy_func, \
|
} \
|
||||||
(GBoxedFreeFunc) free_func); \
|
return g_define_type_id__volatile; \
|
||||||
{ /* custom code follows */
|
} \
|
||||||
|
\
|
||||||
|
G_GNUC_NO_INLINE \
|
||||||
|
static GType \
|
||||||
|
type_name##_get_type_once (void) \
|
||||||
|
{ \
|
||||||
|
GType g_define_type_id = \
|
||||||
|
g_boxed_type_register_static (g_intern_static_string (#TypeName), \
|
||||||
|
(GBoxedCopyFunc) copy_func, \
|
||||||
|
(GBoxedFreeFunc) free_func); \
|
||||||
|
{ /* custom code follows */
|
||||||
#endif /* __GNUC__ */
|
#endif /* __GNUC__ */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2136,15 +2169,27 @@ type_name##_get_type (void) \
|
|||||||
#define G_DEFINE_POINTER_TYPE_WITH_CODE(TypeName, type_name, _C_) _G_DEFINE_POINTER_TYPE_BEGIN (TypeName, type_name) {_C_;} _G_DEFINE_TYPE_EXTENDED_END()
|
#define G_DEFINE_POINTER_TYPE_WITH_CODE(TypeName, type_name, _C_) _G_DEFINE_POINTER_TYPE_BEGIN (TypeName, type_name) {_C_;} _G_DEFINE_TYPE_EXTENDED_END()
|
||||||
|
|
||||||
#define _G_DEFINE_POINTER_TYPE_BEGIN(TypeName, type_name) \
|
#define _G_DEFINE_POINTER_TYPE_BEGIN(TypeName, type_name) \
|
||||||
|
static GType type_name##_get_type_once (void); \
|
||||||
|
\
|
||||||
GType \
|
GType \
|
||||||
type_name##_get_type (void) \
|
type_name##_get_type (void) \
|
||||||
{ \
|
{ \
|
||||||
static volatile gsize g_define_type_id__volatile = 0; \
|
static volatile gsize g_define_type_id__volatile = 0; \
|
||||||
if (g_once_init_enter (&g_define_type_id__volatile)) \
|
if (g_once_init_enter (&g_define_type_id__volatile)) \
|
||||||
{ \
|
{ \
|
||||||
GType g_define_type_id = \
|
GType g_define_type_id = type_name##_get_type_once (); \
|
||||||
g_pointer_type_register_static (g_intern_static_string (#TypeName)); \
|
g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); \
|
||||||
{ /* custom code follows */
|
} \
|
||||||
|
return g_define_type_id__volatile; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
G_GNUC_NO_INLINE \
|
||||||
|
static GType \
|
||||||
|
type_name##_get_type_once (void) \
|
||||||
|
{ \
|
||||||
|
GType g_define_type_id = \
|
||||||
|
g_pointer_type_register_static (g_intern_static_string (#TypeName)); \
|
||||||
|
{ /* custom code follows */
|
||||||
|
|
||||||
/* --- protected (for fundamental type implementations) --- */
|
/* --- protected (for fundamental type implementations) --- */
|
||||||
GLIB_AVAILABLE_IN_ALL
|
GLIB_AVAILABLE_IN_ALL
|
||||||
|
Loading…
x
Reference in New Issue
Block a user