mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-23 20:46:14 +01:00
girepository: Expose GITypeInfo and GIArgInfo as stack allocatable
There are a handful of APIs in libgirepository which are used on performance-sensitive code paths in language bindings (such as looking at arguments when doing function calls). Historically libgirepository has provided a stack-allocated variant for them, which avoids returning a newly allocated `GIBaseInfo`. Since moving to glib.git and porting to `GTypeInstance`, that stack allocated version has been broken. This commit fixes it, by exposing obfuscated stack allocatable versions of `GITypeInfo` and `GIArgInfo`, which are the two `GIBaseInfo` subtypes which can be returned by the stack allocation functions. The commit includes unit tests for them. Signed-off-by: Philip Withnall <pwithnall@gnome.org> Fixes: #3217
This commit is contained in:
parent
5f12851312
commit
2a99d4b168
@ -57,8 +57,15 @@ struct _GIBaseInfo
|
|||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
|
|
||||||
uint32_t type_is_embedded : 1; /* Used by GITypeInfo */
|
uint32_t type_is_embedded : 1; /* Used by GITypeInfo */
|
||||||
|
|
||||||
|
/* A copy of GIBaseInfo is exposed publicly for stack-allocated derivatives
|
||||||
|
* such as GITypeInfo, so its size is now ABI. */
|
||||||
|
void *padding[6];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
G_STATIC_ASSERT (sizeof (GIBaseInfo) == sizeof (GIBaseInfoStack));
|
||||||
|
G_STATIC_ASSERT (G_ALIGNOF (GIBaseInfo) == G_ALIGNOF (GIBaseInfoStack));
|
||||||
|
|
||||||
/* Subtypes */
|
/* Subtypes */
|
||||||
struct _GICallableInfo
|
struct _GICallableInfo
|
||||||
{
|
{
|
||||||
@ -196,18 +203,15 @@ struct _GIFieldInfo
|
|||||||
void gi_field_info_class_init (gpointer g_class,
|
void gi_field_info_class_init (gpointer g_class,
|
||||||
gpointer class_data);
|
gpointer class_data);
|
||||||
|
|
||||||
struct _GIArgInfo
|
/* GIArgInfo is stack-allocatable so it can be used with
|
||||||
{
|
* gi_callable_info_load_return_type() and gi_callable_info_load_arg(), so its
|
||||||
GIBaseInfo parent;
|
* definition is actually public in gitypes.h. */
|
||||||
};
|
|
||||||
|
|
||||||
void gi_arg_info_class_init (gpointer g_class,
|
void gi_arg_info_class_init (gpointer g_class,
|
||||||
gpointer class_data);
|
gpointer class_data);
|
||||||
|
|
||||||
struct _GITypeInfo
|
/* GITypeInfo is stack-allocatable so it can be used with
|
||||||
{
|
* gi_arg_info_load_type(), so its definition is actually public in gitypes.h. */
|
||||||
GIBaseInfo parent;
|
|
||||||
};
|
|
||||||
|
|
||||||
void gi_type_info_class_init (gpointer g_class,
|
void gi_type_info_class_init (gpointer g_class,
|
||||||
gpointer class_data);
|
gpointer class_data);
|
||||||
|
@ -41,6 +41,17 @@ G_BEGIN_DECLS
|
|||||||
typedef struct _GIBaseInfo GIBaseInfo;
|
typedef struct _GIBaseInfo GIBaseInfo;
|
||||||
typedef struct _GIBaseInfoClass GIBaseInfoClass;
|
typedef struct _GIBaseInfoClass GIBaseInfoClass;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
/*< private >*/
|
||||||
|
GTypeInstance parent_instance;
|
||||||
|
|
||||||
|
int dummy0;
|
||||||
|
void *dummy1[3];
|
||||||
|
uint32_t dummy2[2];
|
||||||
|
void *dummy3[6];
|
||||||
|
} GIBaseInfoStack;
|
||||||
|
|
||||||
/* Documented in gicallableinfo.c */
|
/* Documented in gicallableinfo.c */
|
||||||
typedef struct _GICallableInfo GICallableInfo;
|
typedef struct _GICallableInfo GICallableInfo;
|
||||||
GI_AVAILABLE_IN_ALL GType gi_callable_info_get_type (void);
|
GI_AVAILABLE_IN_ALL GType gi_callable_info_get_type (void);
|
||||||
@ -110,11 +121,23 @@ typedef struct _GIFieldInfo GIFieldInfo;
|
|||||||
GI_AVAILABLE_IN_ALL GType gi_field_info_get_type (void);
|
GI_AVAILABLE_IN_ALL GType gi_field_info_get_type (void);
|
||||||
|
|
||||||
/* Documented in giarginfo.c */
|
/* Documented in giarginfo.c */
|
||||||
typedef struct _GIArgInfo GIArgInfo;
|
typedef struct
|
||||||
|
{
|
||||||
|
/*< private >*/
|
||||||
|
GIBaseInfoStack parent;
|
||||||
|
|
||||||
|
void *padding[6];
|
||||||
|
} GIArgInfo;
|
||||||
GI_AVAILABLE_IN_ALL GType gi_arg_info_get_type (void);
|
GI_AVAILABLE_IN_ALL GType gi_arg_info_get_type (void);
|
||||||
|
|
||||||
/* Documented in gitypeinfo.c */
|
/* Documented in gitypeinfo.c */
|
||||||
typedef struct _GITypeInfo GITypeInfo;
|
typedef struct
|
||||||
|
{
|
||||||
|
/*< private >*/
|
||||||
|
GIBaseInfoStack parent;
|
||||||
|
|
||||||
|
void *padding[6];
|
||||||
|
} GITypeInfo;
|
||||||
GI_AVAILABLE_IN_ALL GType gi_type_info_get_type (void);
|
GI_AVAILABLE_IN_ALL GType gi_type_info_get_type (void);
|
||||||
|
|
||||||
/* Documented in giunresolvedinfo.c */
|
/* Documented in giunresolvedinfo.c */
|
||||||
|
@ -152,6 +152,7 @@ test_repository_arg_info (RepositoryFixture *fx,
|
|||||||
GIFunctionInfo *method_info = NULL;
|
GIFunctionInfo *method_info = NULL;
|
||||||
GIArgInfo *arg_info = NULL;
|
GIArgInfo *arg_info = NULL;
|
||||||
GITypeInfo *type_info = NULL;
|
GITypeInfo *type_info = NULL;
|
||||||
|
GITypeInfo type_info_stack;
|
||||||
unsigned int idx;
|
unsigned int idx;
|
||||||
|
|
||||||
g_test_summary ("Test retrieving GIArgInfos from a typelib");
|
g_test_summary ("Test retrieving GIArgInfos from a typelib");
|
||||||
@ -188,7 +189,13 @@ test_repository_arg_info (RepositoryFixture *fx,
|
|||||||
g_assert_true (gi_type_info_is_pointer (type_info));
|
g_assert_true (gi_type_info_is_pointer (type_info));
|
||||||
g_assert_cmpint (gi_type_info_get_tag (type_info), ==, GI_TYPE_TAG_UTF8);
|
g_assert_cmpint (gi_type_info_get_tag (type_info), ==, GI_TYPE_TAG_UTF8);
|
||||||
|
|
||||||
|
gi_arg_info_load_type (arg_info, &type_info_stack);
|
||||||
|
g_assert_true (gi_type_info_is_pointer (&type_info_stack) == gi_type_info_is_pointer (type_info));
|
||||||
|
g_assert_cmpint (gi_type_info_get_tag (&type_info_stack), ==, gi_type_info_get_tag (type_info));
|
||||||
|
|
||||||
|
gi_base_info_clear (&type_info_stack);
|
||||||
g_clear_pointer (&type_info, gi_base_info_unref);
|
g_clear_pointer (&type_info, gi_base_info_unref);
|
||||||
|
|
||||||
g_clear_pointer (&arg_info, gi_base_info_unref);
|
g_clear_pointer (&arg_info, gi_base_info_unref);
|
||||||
g_clear_pointer (&method_info, gi_base_info_unref);
|
g_clear_pointer (&method_info, gi_base_info_unref);
|
||||||
g_clear_pointer (&object_info, gi_base_info_unref);
|
g_clear_pointer (&object_info, gi_base_info_unref);
|
||||||
@ -237,9 +244,11 @@ test_repository_callable_info (RepositoryFixture *fx,
|
|||||||
GIFunctionInfo *method_info = NULL;
|
GIFunctionInfo *method_info = NULL;
|
||||||
GICallableInfo *callable_info;
|
GICallableInfo *callable_info;
|
||||||
GITypeInfo *type_info = NULL;
|
GITypeInfo *type_info = NULL;
|
||||||
|
GITypeInfo type_info_stack;
|
||||||
GIAttributeIter iter = GI_ATTRIBUTE_ITER_INIT;
|
GIAttributeIter iter = GI_ATTRIBUTE_ITER_INIT;
|
||||||
const char *name, *value;
|
const char *name, *value;
|
||||||
GIArgInfo *arg_info = NULL;
|
GIArgInfo *arg_info = NULL;
|
||||||
|
GIArgInfo arg_info_stack;
|
||||||
|
|
||||||
g_test_summary ("Test retrieving GICallableInfos from a typelib");
|
g_test_summary ("Test retrieving GICallableInfos from a typelib");
|
||||||
|
|
||||||
@ -260,6 +269,12 @@ test_repository_callable_info (RepositoryFixture *fx,
|
|||||||
g_assert_nonnull (type_info);
|
g_assert_nonnull (type_info);
|
||||||
g_assert_true (gi_type_info_is_pointer (type_info));
|
g_assert_true (gi_type_info_is_pointer (type_info));
|
||||||
g_assert_cmpint (gi_type_info_get_tag (type_info), ==, GI_TYPE_TAG_VOID);
|
g_assert_cmpint (gi_type_info_get_tag (type_info), ==, GI_TYPE_TAG_VOID);
|
||||||
|
|
||||||
|
gi_callable_info_load_return_type (callable_info, &type_info_stack);
|
||||||
|
g_assert_true (gi_type_info_is_pointer (&type_info_stack) == gi_type_info_is_pointer (type_info));
|
||||||
|
g_assert_cmpint (gi_type_info_get_tag (&type_info_stack), ==, gi_type_info_get_tag (type_info));
|
||||||
|
|
||||||
|
gi_base_info_clear (&type_info_stack);
|
||||||
g_clear_pointer (&type_info, gi_base_info_unref);
|
g_clear_pointer (&type_info, gi_base_info_unref);
|
||||||
|
|
||||||
/* This method has no attributes */
|
/* This method has no attributes */
|
||||||
@ -275,6 +290,12 @@ test_repository_callable_info (RepositoryFixture *fx,
|
|||||||
|
|
||||||
arg_info = gi_callable_info_get_arg (callable_info, 0);
|
arg_info = gi_callable_info_get_arg (callable_info, 0);
|
||||||
g_assert_nonnull (arg_info);
|
g_assert_nonnull (arg_info);
|
||||||
|
|
||||||
|
gi_callable_info_load_arg (callable_info, 0, &arg_info_stack);
|
||||||
|
g_assert_cmpint (gi_arg_info_get_direction (&arg_info_stack), ==, gi_arg_info_get_direction (arg_info));
|
||||||
|
g_assert_true (gi_arg_info_may_be_null (&arg_info_stack) == gi_arg_info_may_be_null (arg_info));
|
||||||
|
|
||||||
|
gi_base_info_clear (&arg_info_stack);
|
||||||
g_clear_pointer (&arg_info, gi_base_info_unref);
|
g_clear_pointer (&arg_info, gi_base_info_unref);
|
||||||
|
|
||||||
g_assert_cmpint (gi_callable_info_get_instance_ownership_transfer (callable_info), ==, GI_TRANSFER_NOTHING);
|
g_assert_cmpint (gi_callable_info_get_instance_ownership_transfer (callable_info), ==, GI_TRANSFER_NOTHING);
|
||||||
|
Loading…
Reference in New Issue
Block a user