Skip to content
This repository has been archived by the owner on Apr 28, 2020. It is now read-only.

Commit

Permalink
gtype: improve get_type fast path
Browse files Browse the repository at this point in the history
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.

To work around this, and return our fast-path to what we had
previously, we need to break out the slow-path (registering the
type) into a secondary function that is not allowed to be 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.

Additionally, this has the benefit of moving the PRELUDE block
added for GSocket deadlock prevention into the once function,
meaning that we do not unconditionally call g_ensure_type()
every time we enter _get_type() functions using PRELUDE.

Compare the hot path for g_socket_get_type() before and after.

Before:

   7e8b0:       f3 0f 1e fa             endbr64
   7e8b4:       55                      push   %rbp
   7e8b5:       53                      push   %rbx
   7e8b6:       48 83 ec 28             sub    $0x28,%rsp
   7e8ba:       64 48 8b 04 25 28 00    mov    %fs:0x28,%rax
   7e8c1:       00 00
   7e8c3:       48 89 44 24 18          mov    %rax,0x18(%rsp)
   7e8c8:       31 c0                   xor    %eax,%eax
   7e8ca:       e8 d1 29 02 00          callq  a12a0 <g_socket_family_get_type@@base>
   7e8cf:       48 89 c7                mov    %rax,%rdi
   7e8d2:       e8 29 81 fb ff          callq  36a00 <g_type_ensure@plt>
   7e8d7:       e8 44 2a 02 00          callq  a1320 <g_socket_type_get_type@@base>
   7e8dc:       48 89 c7                mov    %rax,%rdi
   7e8df:       e8 1c 81 fb ff          callq  36a00 <g_type_ensure@plt>
   7e8e4:       e8 37 2b 02 00          callq  a1420 <g_socket_protocol_get_type@@base>
   7e8e9:       48 89 c7                mov    %rax,%rdi
   7e8ec:       e8 0f 81 fb ff          callq  36a00 <g_type_ensure@plt>
   7e8f1:       e8 ea 64 00 00          callq  84de0 <g_socket_address_get_type@@base>
   7e8f6:       48 89 c7                mov    %rax,%rdi
   7e8f9:       e8 02 81 fb ff          callq  36a00 <g_type_ensure@plt>
   7e8fe:       e8 5d 08 ff ff          callq  6f160 <g_networking_init@@base>
   7e903:       48 8b 05 3e 35 32 00    mov    0x32353e(%rip),%rax        # 3a1e48 <_edata@@base+0x900>
   7e90a:       48 85 c0                test   %rax,%rax
   7e90d:       74 29                   je     7e938 <g_socket_get_type@@base+0x88>
   7e90f:       48 8b 05 32 35 32 00    mov    0x323532(%rip),%rax        # 3a1e48 <_edata@@base+0x900>
   7e916:       48 8b 4c 24 18          mov    0x18(%rsp),%rcx
   7e91b:       64 48 33 0c 25 28 00    xor    %fs:0x28,%rcx
   7e922:       00 00
   7e924:       0f 85 e5 00 00 00       jne    7ea0f <g_socket_get_type@@base+0x15f>
   7e92a:       48 83 c4 28             add    $0x28,%rsp
   7e92e:       5b                      pop    %rbx
   7e92f:       5d                      pop    %rbp
   7e930:       c3                      retq

After:

   7fbe0:       48 8b 05 21 ae 32 00    mov    0x32ae21(%rip),%rax        # 3aaa08 <g_define_type_id__volatile.18420>
   7fbe7:       48 85 c0                test   %rax,%rax
   7fbea:       74 0c                   je     7fbf8 <g_socket_get_type+0x18>
   7fbec:       48 8b 05 15 ae 32 00    mov    0x32ae15(%rip),%rax        # 3aaa08 <g_define_type_id__volatile.18420>
   7fbf3:       c3                      retq

https://bugzilla.gnome.org/show_bug.cgi?id=795180
  • Loading branch information
chergert authored and GeorgesStavracas committed Apr 25, 2018
1 parent 1290307 commit d4c2a49
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 64 deletions.
2 changes: 1 addition & 1 deletion gobject/gtype-private.h
Expand Up @@ -100,7 +100,7 @@ void _g_closure_invoke_va (GClosure *closure,
*
* Currently private.
*/
#define _G_DEFINE_TYPE_EXTENDED_WITH_PRELUDE(TN, t_n, T_P, _f_, _P_, _C_) _G_DEFINE_TYPE_EXTENDED_BEGIN_PRE (TN, t_n, T_P) {_P_;} _G_DEFINE_TYPE_EXTENDED_BEGIN_REGISTER (TN, t_n, T_P, _f_){_C_;} _G_DEFINE_TYPE_EXTENDED_END()
#define _G_DEFINE_TYPE_EXTENDED_WITH_PRELUDE(TN, t_n, T_P, _f_, _P_, _C_) _G_DEFINE_TYPE_EXTENDED_BEGIN_PRE (TN, t_n, T_P) {_P_;} _G_DEFINE_TYPE_EXTENDED_BEGIN_REGISTER (TN, t_n, T_P, _f_){_C_;} _G_DEFINE_TYPE_EXTENDED_END(t_n)

G_END_DECLS

Expand Down
129 changes: 66 additions & 63 deletions gobject/gtype.h
Expand Up @@ -1607,7 +1607,7 @@ guint g_type_get_type_registration_serial (void);
*
* Since: 2.4
*/
#define G_DEFINE_TYPE_WITH_CODE(TN, t_n, T_P, _C_) _G_DEFINE_TYPE_EXTENDED_BEGIN (TN, t_n, T_P, 0) {_C_;} _G_DEFINE_TYPE_EXTENDED_END()
#define G_DEFINE_TYPE_WITH_CODE(TN, t_n, T_P, _C_) _G_DEFINE_TYPE_EXTENDED_BEGIN (TN, t_n, T_P, 0) {_C_;} _G_DEFINE_TYPE_EXTENDED_END(t_n)
/**
* G_DEFINE_TYPE_WITH_PRIVATE:
* @TN: The name of the new type, in Camel case.
Expand Down Expand Up @@ -1658,7 +1658,7 @@ guint g_type_get_type_registration_serial (void);
*
* Since: 2.4
*/
#define G_DEFINE_ABSTRACT_TYPE_WITH_CODE(TN, t_n, T_P, _C_) _G_DEFINE_TYPE_EXTENDED_BEGIN (TN, t_n, T_P, G_TYPE_FLAG_ABSTRACT) {_C_;} _G_DEFINE_TYPE_EXTENDED_END()
#define G_DEFINE_ABSTRACT_TYPE_WITH_CODE(TN, t_n, T_P, _C_) _G_DEFINE_TYPE_EXTENDED_BEGIN (TN, t_n, T_P, G_TYPE_FLAG_ABSTRACT) {_C_;} _G_DEFINE_TYPE_EXTENDED_END(t_n)
/**
* G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE:
* @TN: The name of the new type, in Camel case.
Expand Down Expand Up @@ -1734,7 +1734,7 @@ guint g_type_get_type_registration_serial (void);
*
* Since: 2.4
*/
#define G_DEFINE_TYPE_EXTENDED(TN, t_n, T_P, _f_, _C_) _G_DEFINE_TYPE_EXTENDED_BEGIN (TN, t_n, T_P, _f_) {_C_;} _G_DEFINE_TYPE_EXTENDED_END()
#define G_DEFINE_TYPE_EXTENDED(TN, t_n, T_P, _f_, _C_) _G_DEFINE_TYPE_EXTENDED_BEGIN (TN, t_n, T_P, _f_) {_C_;} _G_DEFINE_TYPE_EXTENDED_END(t_n)

/**
* G_DEFINE_INTERFACE:
Expand Down Expand Up @@ -1960,32 +1960,41 @@ type_name##_get_instance_private (TypeName *self) \
return (G_STRUCT_MEMBER_P (self, TypeName##_private_offset)); \
} \
\
GType \
type_name##_get_type (void) \
G_GNUC_NO_INLINE \
static GType \
type_name##_get_type_once (void) \
{ \
static volatile gsize g_define_type_id__volatile = 0;
GType g_define_type_id = 0;
/* Prelude goes here */

/* Added for _G_DEFINE_TYPE_EXTENDED_WITH_PRELUDE */
#define _G_DEFINE_TYPE_EXTENDED_BEGIN_REGISTER(TypeName, type_name, TYPE_PARENT, flags) \
g_define_type_id = \
g_type_register_static_simple (TYPE_PARENT, \
g_intern_static_string (#TypeName), \
sizeof (TypeName##Class), \
(GClassInitFunc)(void (*)(void)) type_name##_class_intern_init, \
sizeof (TypeName), \
(GInstanceInitFunc)(void (*)(void)) type_name##_init, \
(GTypeFlags) flags); \
{ /* custom code follows */
#define _G_DEFINE_TYPE_EXTENDED_END(type_name) \
} /* following custom code */ \
\
return g_define_type_id; \
} /* closes type_name##_get_type_once() */ \
\
GType \
type_name##_get_type (void) \
{ \
static volatile gsize g_define_type_id__volatile = 0; \
if (g_once_init_enter (&g_define_type_id__volatile)) \
{ \
GType g_define_type_id = \
g_type_register_static_simple (TYPE_PARENT, \
g_intern_static_string (#TypeName), \
sizeof (TypeName##Class), \
(GClassInitFunc) type_name##_class_intern_init, \
sizeof (TypeName), \
(GInstanceInitFunc) type_name##_init, \
(GTypeFlags) flags); \
{ /* custom code follows */
#define _G_DEFINE_TYPE_EXTENDED_END() \
/* following custom code */ \
} \
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() */
} \
return g_define_type_id__volatile; \
} /* closes type_name##_get_type_once() */

/* This was defined before we had G_DEFINE_TYPE_WITH_CODE_AND_PRELUDE, it's simplest
* to keep it.
Expand Down Expand Up @@ -2063,49 +2072,45 @@ type_name##_get_type (void) \
*
* Since: 2.26
*/
#define G_DEFINE_BOXED_TYPE_WITH_CODE(TypeName, type_name, copy_func, free_func, _C_) _G_DEFINE_BOXED_TYPE_BEGIN (TypeName, type_name, copy_func, free_func) {_C_;} _G_DEFINE_TYPE_EXTENDED_END()
#define G_DEFINE_BOXED_TYPE_WITH_CODE(TypeName, type_name, copy_func, free_func, _C_) _G_DEFINE_BOXED_TYPE_BEGIN (TypeName, type_name, copy_func, free_func) {_C_;} _G_DEFINE_TYPE_EXTENDED_END(type_name)

/* Only use this in non-C++ on GCC >= 2.7, except for Darwin/ppc64.
* See https://bugzilla.gnome.org/show_bug.cgi?id=647145
*/
#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) \
GType \
type_name##_get_type (void) \
G_GNUC_NO_INLINE \
static GType \
type_name##_get_type_once (void) \
{ \
static volatile gsize g_define_type_id__volatile = 0; \
if (g_once_init_enter (&g_define_type_id__volatile)) \
{ \
GType (* _g_register_boxed) \
(const gchar *, \
union \
{ \
TypeName * (*do_copy_type) (TypeName *); \
TypeName * (*do_const_copy_type) (const TypeName *); \
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 */
GType (* _g_register_boxed) \
(const gchar *, \
union \
{ \
TypeName * (*do_copy_type) (TypeName *); \
TypeName * (*do_const_copy_type) (const TypeName *); \
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
#define _G_DEFINE_BOXED_TYPE_BEGIN(TypeName, type_name, copy_func, free_func) \
GType \
type_name##_get_type (void) \
G_GNUC_NO_INLINE \
static GType \
type_name##_get_type_once (void) \
{ \
static volatile gsize g_define_type_id__volatile = 0; \
if (g_once_init_enter (&g_define_type_id__volatile)) \
{ \
GType g_define_type_id = \
g_boxed_type_register_static (g_intern_static_string (#TypeName), \
(GBoxedCopyFunc) copy_func, \
(GBoxedFreeFunc) free_func); \
{ /* custom code follows */
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__ */

/**
Expand Down Expand Up @@ -2133,18 +2138,16 @@ type_name##_get_type (void) \
*
* Since: 2.26
*/
#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(type_name)

#define _G_DEFINE_POINTER_TYPE_BEGIN(TypeName, type_name) \
GType \
type_name##_get_type (void) \
G_GNUC_NO_INLINE \
static GType \
type_name##_get_type_once (void) \
{ \
static volatile gsize g_define_type_id__volatile = 0; \
if (g_once_init_enter (&g_define_type_id__volatile)) \
{ \
GType g_define_type_id = \
g_pointer_type_register_static (g_intern_static_string (#TypeName)); \
{ /* custom code follows */
GType g_define_type_id = \
g_pointer_type_register_static (g_intern_static_string (#TypeName)); \
{ /* custom code follows */

/* --- protected (for fundamental type implementations) --- */
GLIB_AVAILABLE_IN_ALL
Expand Down

0 comments on commit d4c2a49

Please sign in to comment.