[glib/gobject-speedups: 18/23] Avoid g_type_peek_value_table




commit 467161cd5cca0e5187082dd03eec24f78274edd9
Author: Matthias Clasen <mclasen redhat com>
Date:   Thu May 19 19:57:50 2022 -0400

    Avoid g_type_peek_value_table
    
    In several places we do paired calls of g_value_init
    and g_value_unset, both of which peek the value table.
    We can avoid half of that cost by remembering the value
    table.

 gobject/gobject.c         | 20 ++++++++++++++++----
 gobject/gvaluecollector.h | 14 ++++++++++----
 2 files changed, 26 insertions(+), 8 deletions(-)
---
diff --git a/gobject/gobject.c b/gobject/gobject.c
index bed3a19623..12135b6a9c 100644
--- a/gobject/gobject.c
+++ b/gobject/gobject.c
@@ -2341,9 +2341,11 @@ g_object_new_valist (GType        object_type,
     {
       GObjectConstructParam params_stack[16];
       GValue values_stack[G_N_ELEMENTS (params_stack)];
+      GTypeValueTable *vtabs_stack[G_N_ELEMENTS (params_stack)];
       const gchar *name;
       GObjectConstructParam *params = params_stack;
       GValue *values = values_stack;
+      GTypeValueTable **vtabs = vtabs_stack;
       guint n_params = 0;
       guint n_params_alloc = G_N_ELEMENTS (params_stack);
 
@@ -2368,14 +2370,17 @@ g_object_new_valist (GType        object_type,
                   n_params_alloc = G_N_ELEMENTS (params_stack) * 2u;
                   params = g_new (GObjectConstructParam, n_params_alloc);
                   values = g_new (GValue, n_params_alloc);
+                  vtabs = g_new (GTypeValueTable *, n_params_alloc);
                   memcpy (params, params_stack, sizeof (GObjectConstructParam) * n_params);
                   memcpy (values, values_stack, sizeof (GValue) * n_params);
+                  memcpy (vtabs, vtabs_stack, sizeof (GTypeValueTable *) * n_params);
                 }
               else
                 {
                   n_params_alloc *= 2u;
                   params = g_realloc (params, sizeof (GObjectConstructParam) * n_params_alloc);
                   values = g_realloc (values, sizeof (GValue) * n_params_alloc);
+                  vtabs = g_realloc (vtabs, sizeof (GTypeValueTable *) * n_params_alloc);
                 }
 
               for (i = 0; i < n_params; i++)
@@ -2386,7 +2391,7 @@ g_object_new_valist (GType        object_type,
           params[n_params].value = &values[n_params];
           memset (&values[n_params], 0, sizeof (GValue));
 
-          G_VALUE_COLLECT_INIT (&values[n_params], pspec->value_type, var_args, G_VALUE_NOCOPY_CONTENTS, 
&error);
+          G_VALUE_COLLECT_INIT2 (&values[n_params], vtabs[n_params], pspec->value_type, var_args, 
G_VALUE_NOCOPY_CONTENTS, &error);
 
           if (error)
             {
@@ -2403,12 +2408,16 @@ g_object_new_valist (GType        object_type,
       object = g_object_new_internal (class, params, n_params);
 
       while (n_params--)
-        g_value_unset (params[n_params].value);
+        {
+          if (vtabs[n_params]->value_free)
+            vtabs[n_params]->value_free (params[n_params].value);
+        }
 
       if (G_UNLIKELY (n_params_alloc != G_N_ELEMENTS (params_stack)))
         {
           g_free (params);
           g_free (values);
+          g_free (vtabs);
         }
     }
   else
@@ -2569,6 +2578,7 @@ g_object_set_valist (GObject       *object,
       GValue value = G_VALUE_INIT;
       GParamSpec *pspec;
       gchar *error = NULL;
+      GTypeValueTable *vtab;
       
       pspec = g_param_spec_pool_lookup (pspec_pool,
                                        name,
@@ -2578,7 +2588,7 @@ g_object_set_valist (GObject       *object,
       if (!g_object_set_is_valid_property (object, pspec, name))
         break;
 
-      G_VALUE_COLLECT_INIT (&value, pspec->value_type, var_args, G_VALUE_NOCOPY_CONTENTS, &error);
+      G_VALUE_COLLECT_INIT2 (&value, vtab, pspec->value_type, var_args, G_VALUE_NOCOPY_CONTENTS, &error);
       if (error)
        {
          g_warning ("%s: %s", G_STRFUNC, error);
@@ -2588,7 +2598,9 @@ g_object_set_valist (GObject       *object,
        }
 
       object_set_property (object, pspec, &value, nqueue);
-      g_value_unset (&value);
+
+      if (vtab->value_free)
+        vtab->value_free (&value);
 
       name = va_arg (var_args, gchar*);
     }
diff --git a/gobject/gvaluecollector.h b/gobject/gvaluecollector.h
index 82e675cdd9..b782f40705 100644
--- a/gobject/gvaluecollector.h
+++ b/gobject/gvaluecollector.h
@@ -87,15 +87,21 @@ union _GTypeCValue
  *
  * Since: 2.24
  */
-#define G_VALUE_COLLECT_INIT(value, _value_type, var_args, flags, __error)             \
+#define G_VALUE_COLLECT_INIT(value, _value_type, var_args, flags, __error) \
+  G_STMT_START { \
+    GTypeValueTable *g_vci_vtab; \
+    G_VALUE_COLLECT_INIT2(value, g_vci_vtab, _value_type, var_args, flags, __error); \
+} G_STMT_END
+
+#define G_VALUE_COLLECT_INIT2(value, g_vci_vtab, _value_type, var_args, flags, __error)                \
 G_STMT_START {                                                                         \
   GValue *g_vci_val = (value);                                                         \
   guint g_vci_flags = (flags);                                                         \
-  GTypeValueTable *g_vci_vtab = g_type_value_table_peek (_value_type);                 \
-  const gchar *g_vci_collect_format = g_vci_vtab->collect_format;                                      \
+  const gchar *g_vci_collect_format; \
   GTypeCValue g_vci_cvalues[G_VALUE_COLLECT_FORMAT_MAX_LENGTH] = { { 0, }, };          \
   guint g_vci_n_values = 0;                                                                    \
-                                                                                        \
+  g_vci_vtab = g_type_value_table_peek (_value_type);                  \
+  g_vci_collect_format = g_vci_vtab->collect_format;                                   \
   g_vci_val->g_type = _value_type;             /* value_meminit() from gvalue.c */             \
   while (*g_vci_collect_format)                                                                \
     {                                                                                  \


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]