summaryrefslogtreecommitdiff
path: root/gobject
diff options
context:
space:
mode:
authorChristian Hergert <chergert@redhat.com>2023-09-26 14:32:45 -0700
committerPhilip Withnall <pwithnall@endlessos.org>2023-10-03 09:44:32 +0100
commit5de7dd5a4b0f7a55bd3b642268875c3a19d184a6 (patch)
treedf51bde9df2e16f7f338b1be6cc4644c313beca1 /gobject
parentec8c62d76524d868feb16bb060495a822e733105 (diff)
gobject: cache flags needed for g_type_create_instance()
Every call to g_type_create_instance() currently will incur a RWLock at least once, but usually twice to test for both G_TYPE_FLAG_ABSTRACT and G_TYPE_FLAG_DEPRECATED. Additionally, each call to g_type_instance_free() also checks for these. That results in a synchronization of GTypeInstance creation across all threads as well as being a huge amount of overhead when creating instances like GskRenderNode. With this patch in place, the next two biggest issues are g_type_class_ref() and g_type_test_flags() not getting inlined within gtype.c in release builds. We can address that separately though. Sysprof shows that the RWLock, with this patch in place, falls off the profiles.
Diffstat (limited to 'gobject')
-rw-r--r--gobject/gtype.c48
1 files changed, 32 insertions, 16 deletions
diff --git a/gobject/gtype.c b/gobject/gtype.c
index e2e0c3873..0718b05d3 100644
--- a/gobject/gtype.c
+++ b/gobject/gtype.c
@@ -163,7 +163,9 @@
/* List the flags that are directly accessible via the TypeNode struct flags */
#define NODE_FLAG_MASK ( \
+ G_TYPE_FLAG_ABSTRACT | \
G_TYPE_FLAG_CLASSED | \
+ G_TYPE_FLAG_DEPRECATED | \
G_TYPE_FLAG_INSTANTIATABLE | \
G_TYPE_FLAG_FINAL)
@@ -252,7 +254,9 @@ struct _TypeNode
guint n_children; /* writable with lock */
guint n_supers : 8;
guint n_prerequisites : 9;
+ guint is_abstract : 1;
guint is_classed : 1;
+ guint is_deprecated : 1;
guint is_instantiatable : 1;
guint is_final : 1;
guint mutatable_check_cache : 1; /* combines some common path checks */
@@ -482,7 +486,9 @@ type_node_any_new_W (TypeNode *pnode,
node->supers[0] = type;
node->supers[1] = 0;
+ node->is_abstract = (type_flags & G_TYPE_FLAG_ABSTRACT) != 0;
node->is_classed = (type_flags & G_TYPE_FLAG_CLASSED) != 0;
+ node->is_deprecated = (type_flags & G_TYPE_FLAG_DEPRECATED) != 0;
node->is_instantiatable = (type_flags & G_TYPE_FLAG_INSTANTIATABLE) != 0;
if (NODE_IS_IFACE (node))
@@ -498,9 +504,13 @@ type_node_any_new_W (TypeNode *pnode,
node->supers[0] = type;
memcpy (node->supers + 1, pnode->supers, sizeof (GType) * (1 + pnode->n_supers + 1));
+ node->is_abstract = (type_flags & G_TYPE_FLAG_ABSTRACT) != 0;
node->is_classed = pnode->is_classed;
+ node->is_deprecated = (type_flags & G_TYPE_FLAG_DEPRECATED) != 0;
node->is_instantiatable = pnode->is_instantiatable;
-
+
+ node->is_deprecated |= pnode->is_deprecated;
+
if (NODE_IS_IFACE (node))
{
IFACE_NODE_N_PREREQUISITES (node) = 0;
@@ -566,20 +576,18 @@ type_node_fundamental_new_W (GType ftype,
{
GTypeFundamentalInfo *finfo;
TypeNode *node;
-
+
g_assert ((ftype & TYPE_ID_MASK) == 0);
g_assert (ftype <= G_TYPE_FUNDAMENTAL_MAX);
-
+
if (ftype >> G_TYPE_FUNDAMENTAL_SHIFT == static_fundamental_next)
static_fundamental_next++;
-
- type_flags &= TYPE_FUNDAMENTAL_FLAG_MASK;
-
+
node = type_node_any_new_W (NULL, ftype, name, NULL, type_flags);
-
+
finfo = type_node_fundamental_info_I (node);
- finfo->type_flags = type_flags;
-
+ finfo->type_flags = type_flags & TYPE_FUNDAMENTAL_FLAG_MASK;
+
return node;
}
@@ -3919,6 +3927,8 @@ type_add_flags_W (TypeNode *node,
dflags |= flags;
type_set_qdata_W (node, static_quark_type_flags, GUINT_TO_POINTER (dflags));
+ node->is_abstract = (flags & G_TYPE_FLAG_ABSTRACT) != 0;
+ node->is_deprecated |= (flags & G_TYPE_FLAG_DEPRECATED) != 0;
node->is_final = (flags & G_TYPE_FLAG_FINAL) != 0;
}
@@ -4007,16 +4017,22 @@ g_type_test_flags (GType type,
{
if ((flags & ~NODE_FLAG_MASK) == 0)
{
- if (flags & G_TYPE_FLAG_CLASSED)
- result |= node->is_classed;
+ if ((flags & G_TYPE_FLAG_CLASSED) && !node->is_classed)
+ return FALSE;
+
+ if ((flags & G_TYPE_FLAG_INSTANTIATABLE) && !node->is_instantiatable)
+ return FALSE;
+
+ if ((flags & G_TYPE_FLAG_FINAL) && !node->is_final)
+ return FALSE;
- if (flags & G_TYPE_FLAG_INSTANTIATABLE)
- result |= node->is_instantiatable;
+ if ((flags & G_TYPE_FLAG_ABSTRACT) && !node->is_abstract)
+ return FALSE;
- if (flags & G_TYPE_FLAG_FINAL)
- result |= node->is_final;
+ if ((flags & G_TYPE_FLAG_DEPRECATED) && !node->is_deprecated)
+ return FALSE;
- return result;
+ return TRUE;
}
guint fflags = flags & TYPE_FUNDAMENTAL_FLAG_MASK;