[gtk/matthiasc/css-value-inner-loop] css: Reshuffle the inner loop of value computation



commit 4ab0e7956eb90e9d99ba686117fb1896cfc4f31a
Author: Matthias Clasen <mclasen redhat com>
Date:   Fri Jan 24 22:52:38 2020 -0500

    css: Reshuffle the inner loop of value computation
    
    The loop over all properties in gtk_css_static_style_compute_values
    is the inner loop of the css value computation, we hit it thousands
    of times per frame. Rearrange things to make this faster, by avoiding
    function calls, pulling the section handling out of the separate loop,
    and handling the border-width special case in a neater way.
    
    Before: 50 runs, min 12.45, max 20.419, avg 15.9414
    After:  50 runs, min 12.622, max 21.195, avg 15.0449

 gtk/gtkcsslookup.c               |  38 +------
 gtk/gtkcsslookupprivate.h        |   5 +-
 gtk/gtkcssstaticstyle.c          | 215 +++++++++++++++++++++------------------
 gtk/gtkcssstaticstyleprivate.h   |   8 --
 gtk/gtkcssstylepropertyimpl.c    |   6 ++
 gtk/gtkcssstylepropertyprivate.h |   7 ++
 6 files changed, 131 insertions(+), 148 deletions(-)
---
diff --git a/gtk/gtkcsslookup.c b/gtk/gtkcsslookup.c
index cfe5bfc5c5..3869840f59 100644
--- a/gtk/gtkcsslookup.c
+++ b/gtk/gtkcsslookup.c
@@ -76,40 +76,6 @@ _gtk_css_lookup_set (GtkCssLookup  *lookup,
   lookup->values[id].value = value;
   lookup->values[id].section = section;
   lookup->n_set_values ++;
-}
-
-/**
- * _gtk_css_lookup_resolve:
- * @lookup: the lookup
- * @context: the context the values are resolved for
- * @values: a new #GtkCssStyle to be filled with the new properties
- *
- * Resolves the current lookup into a styleproperties object. This is done
- * by converting from the “winning declaration” to the “computed value”.
- *
- * XXX: This bypasses the notion of “specified value”. If this ever becomes
- * an issue, go fix it.
- **/
-void
-_gtk_css_lookup_resolve (GtkCssLookup      *lookup,
-                         GtkStyleProvider  *provider,
-                         GtkCssStaticStyle *style,
-                         GtkCssStyle       *parent_style)
-{
-  guint i;
-
-  gtk_internal_return_if_fail (lookup != NULL);
-  gtk_internal_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
-  gtk_internal_return_if_fail (GTK_IS_CSS_STATIC_STYLE (style));
-  gtk_internal_return_if_fail (parent_style == NULL || GTK_IS_CSS_STYLE (parent_style));
-
-  for (i = 0; i < GTK_CSS_PROPERTY_N_PROPERTIES; i++)
-    {
-      gtk_css_static_style_compute_value (style,
-                                          provider,
-                                          parent_style,
-                                          i,
-                                          lookup->values[i].value,
-                                          lookup->values[i].section);
-    }
+  if (section)
+    lookup->has_section = TRUE;
 }
diff --git a/gtk/gtkcsslookupprivate.h b/gtk/gtkcsslookupprivate.h
index 34acd504c3..3e9915d4d4 100644
--- a/gtk/gtkcsslookupprivate.h
+++ b/gtk/gtkcsslookupprivate.h
@@ -37,6 +37,7 @@ typedef struct {
 
 struct _GtkCssLookup {
   guint              n_set_values;
+  gboolean           has_section;
   GtkCssLookupValue  values[GTK_CSS_PROPERTY_N_PROPERTIES];
 };
 
@@ -49,10 +50,6 @@ void                    _gtk_css_lookup_set                     (GtkCssLookup
                                                                  guint                       id,
                                                                  GtkCssSection              *section,
                                                                  GtkCssValue                *value);
-void                    _gtk_css_lookup_resolve                 (GtkCssLookup               *lookup,
-                                                                 GtkStyleProvider           *provider,
-                                                                 GtkCssStaticStyle          *style,
-                                                                 GtkCssStyle                *parent_style);
 
 G_END_DECLS
 
diff --git a/gtk/gtkcssstaticstyle.c b/gtk/gtkcssstaticstyle.c
index 0c6b8da04b..f99f9efbc6 100644
--- a/gtk/gtkcssstaticstyle.c
+++ b/gtk/gtkcssstaticstyle.c
@@ -115,34 +115,6 @@ maybe_unref_section (gpointer section)
     gtk_css_section_unref (section);
 }
 
-static void
-gtk_css_static_style_set_value (GtkCssStaticStyle *style,
-                                guint              id,
-                                GtkCssValue       *value,
-                                GtkCssSection     *section)
-{
-  if (style->values[id])
-    _gtk_css_value_unref (style->values[id]);
-
-  style->values[id] = value;
-
-  if (style->sections && style->sections->len > id && g_ptr_array_index (style->sections, id))
-    {
-      gtk_css_section_unref (g_ptr_array_index (style->sections, id));
-      g_ptr_array_index (style->sections, id) = NULL;
-    }
-
-  if (section)
-    {
-      if (style->sections == NULL)
-        style->sections = g_ptr_array_new_with_free_func (maybe_unref_section);
-      if (style->sections->len <= id)
-        g_ptr_array_set_size (style->sections, id + 1);
-
-      g_ptr_array_index (style->sections, id) = gtk_css_section_ref (section);
-    }
-}
-
 static GtkCssStyle *default_style;
 
 static void
@@ -175,6 +147,120 @@ gtk_css_static_style_get_default (void)
   return default_style;
 }
 
+G_STATIC_ASSERT (GTK_CSS_PROPERTY_BORDER_TOP_STYLE == GTK_CSS_PROPERTY_BORDER_TOP_WIDTH - 1);
+G_STATIC_ASSERT (GTK_CSS_PROPERTY_BORDER_RIGHT_STYLE == GTK_CSS_PROPERTY_BORDER_RIGHT_WIDTH - 1);
+G_STATIC_ASSERT (GTK_CSS_PROPERTY_BORDER_BOTTOM_STYLE == GTK_CSS_PROPERTY_BORDER_BOTTOM_WIDTH - 1);
+G_STATIC_ASSERT (GTK_CSS_PROPERTY_BORDER_LEFT_STYLE == GTK_CSS_PROPERTY_BORDER_LEFT_WIDTH - 1);
+G_STATIC_ASSERT (GTK_CSS_PROPERTY_OUTLINE_STYLE == GTK_CSS_PROPERTY_OUTLINE_WIDTH - 1);
+
+static inline gboolean
+is_border_style_special_case (guint id)
+{
+  switch (id)
+    {
+    case GTK_CSS_PROPERTY_BORDER_TOP_STYLE:
+    case GTK_CSS_PROPERTY_BORDER_RIGHT_STYLE:
+    case GTK_CSS_PROPERTY_BORDER_BOTTOM_STYLE:
+    case GTK_CSS_PROPERTY_BORDER_LEFT_STYLE:
+    case GTK_CSS_PROPERTY_OUTLINE_STYLE:
+      return TRUE;
+    default:
+      return FALSE;
+   }
+}
+
+static void
+gtk_css_static_style_compute_values (GtkCssStaticStyle *style,
+                                     GtkStyleProvider  *provider,
+                                     GtkCssStyle       *parent_style,
+                                     GtkCssLookup      *lookup)
+{
+  GtkCssLookupValue *values = lookup->values;
+  guint id;
+  GtkCssValue **parent_values;
+  guint border_prop[] = {
+    GTK_CSS_PROPERTY_BORDER_TOP_STYLE,
+    GTK_CSS_PROPERTY_BORDER_LEFT_STYLE,
+    GTK_CSS_PROPERTY_BORDER_BOTTOM_STYLE,
+    GTK_CSS_PROPERTY_BORDER_RIGHT_STYLE,
+    GTK_CSS_PROPERTY_OUTLINE_STYLE,
+    0
+  };
+  int b = 0;
+
+  if (GTK_IS_CSS_STATIC_STYLE (parent_style))
+    parent_values = GTK_CSS_STATIC_STYLE (parent_style)->values;
+  else
+    parent_values = NULL;
+
+  for (id = 0; id < GTK_CSS_PROPERTY_N_PROPERTIES; id++)
+    {
+      GtkCssValue *specified = values[id].value;
+
+      /* http://www.w3.org/TR/css3-cascade/#cascade
+       * Then, for every element, the value for each property can be found
+       * by following this pseudo-algorithm:
+       * 1) Identify all declarations that apply to the element
+       */
+      if (specified)
+        {
+          style->values[id] = _gtk_css_value_compute (specified, id, provider, (GtkCssStyle *)style, 
parent_style);
+
+          /* special case according to http://dev.w3.org/csswg/css-backgrounds/#the-border-width */
+          if (id == border_prop[b])
+            {
+              b++;
+              /* We have them ordered in gtkcssstylepropertyimpl.c accordingly, so the
+               * border styles are computed before the border widths.
+               * Note that we rely on ..._WIDTH == ..._STYLE + 1 here.
+               */
+              GtkBorderStyle border_style = _gtk_css_border_style_value_get (style->values[id]);
+              if (border_style == GTK_BORDER_STYLE_NONE || border_style == GTK_BORDER_STYLE_HIDDEN)
+                {
+                  id++;
+                  style->values[id] = gtk_css_dimension_value_new (0, GTK_CSS_NUMBER);
+                }
+            }
+        }
+      else if (parent_values && gtk_css_style_property_is_inherit (id))
+        {
+          style->values[id] = _gtk_css_value_ref (parent_values[id]);
+
+          /* the border properties are not inherit, so no need to check the special case here */
+        }
+      else if (parent_style && gtk_css_style_property_is_inherit (id))
+        {
+          style->values[id] = _gtk_css_value_ref (gtk_css_style_get_value (parent_style, id));
+
+          /* the border properties are not inherit, so no need to check the special case here */
+        }
+      else
+        {
+          style->values[id] = _gtk_css_initial_value_new_compute (id, provider, (GtkCssStyle *)style, 
parent_style);
+
+          /* special case according to http://dev.w3.org/csswg/css-backgrounds/#the-border-width */
+          if (id == border_prop[b])
+            {
+              b++;
+              /* no need to check the value. The initial value of the border-style properties is none */
+              id++;
+              style->values[id] = gtk_css_dimension_value_new (0, GTK_CSS_NUMBER);
+            }
+        }
+    }
+
+  if (lookup->has_section)
+    {
+      style->sections = g_ptr_array_new_full (GTK_CSS_PROPERTY_N_PROPERTIES, maybe_unref_section);
+      for (id = 0; id < GTK_CSS_PROPERTY_N_PROPERTIES; id++)
+        {
+          GtkCssSection *section = values[id].section;
+          if (section)
+            g_ptr_array_index (style->sections, id) = gtk_css_section_ref (section);
+        }
+    }
+}
+
 GtkCssStyle *
 gtk_css_static_style_new_compute (GtkStyleProvider    *provider,
                                   const GtkCssMatcher *matcher,
@@ -196,84 +282,13 @@ gtk_css_static_style_new_compute (GtkStyleProvider    *provider,
 
   result->change = change;
 
-  _gtk_css_lookup_resolve (&lookup,
-                           provider,
-                           result,
-                           parent);
+  gtk_css_static_style_compute_values (result, provider, parent, &lookup);
 
   _gtk_css_lookup_destroy (&lookup);
 
   return GTK_CSS_STYLE (result);
 }
 
-G_STATIC_ASSERT (GTK_CSS_PROPERTY_BORDER_TOP_STYLE == GTK_CSS_PROPERTY_BORDER_TOP_WIDTH - 1);
-G_STATIC_ASSERT (GTK_CSS_PROPERTY_BORDER_RIGHT_STYLE == GTK_CSS_PROPERTY_BORDER_RIGHT_WIDTH - 1);
-G_STATIC_ASSERT (GTK_CSS_PROPERTY_BORDER_BOTTOM_STYLE == GTK_CSS_PROPERTY_BORDER_BOTTOM_WIDTH - 1);
-G_STATIC_ASSERT (GTK_CSS_PROPERTY_BORDER_LEFT_STYLE == GTK_CSS_PROPERTY_BORDER_LEFT_WIDTH - 1);
-G_STATIC_ASSERT (GTK_CSS_PROPERTY_OUTLINE_STYLE == GTK_CSS_PROPERTY_OUTLINE_WIDTH - 1);
-
-void
-gtk_css_static_style_compute_value (GtkCssStaticStyle *style,
-                                    GtkStyleProvider  *provider,
-                                    GtkCssStyle       *parent_style,
-                                    guint              id,
-                                    GtkCssValue       *specified,
-                                    GtkCssSection     *section)
-{
-  GtkCssValue *value;
-  GtkBorderStyle border_style;
-
-  gtk_internal_return_if_fail (id < GTK_CSS_PROPERTY_N_PROPERTIES);
-
-  /* special case according to http://dev.w3.org/csswg/css-backgrounds/#the-border-width */
-  switch (id)
-    {
-      /* We have them ordered in gtkcssstylepropertyimpl.c accordingly, so the
-       * border styles are already computed when we compute the border widths.
-       *
-       * Note that we rely on ..._STYLE == ..._WIDTH - 1 here.
-       */
-      case GTK_CSS_PROPERTY_BORDER_TOP_WIDTH:
-      case GTK_CSS_PROPERTY_BORDER_RIGHT_WIDTH:
-      case GTK_CSS_PROPERTY_BORDER_BOTTOM_WIDTH:
-      case GTK_CSS_PROPERTY_BORDER_LEFT_WIDTH:
-      case GTK_CSS_PROPERTY_OUTLINE_WIDTH:
-        border_style = _gtk_css_border_style_value_get (gtk_css_style_get_value ((GtkCssStyle *)style, id - 
1));
-        if (border_style == GTK_BORDER_STYLE_NONE || border_style == GTK_BORDER_STYLE_HIDDEN)
-          {
-            gtk_css_static_style_set_value (style, id, gtk_css_dimension_value_new (0, GTK_CSS_NUMBER), 
section);
-            return;
-          }
-        break;
-
-      default:
-        /* Go ahead */
-        break;
-    }
-
-
-  /* http://www.w3.org/TR/css3-cascade/#cascade
-   * Then, for every element, the value for each property can be found
-   * by following this pseudo-algorithm:
-   * 1) Identify all declarations that apply to the element
-   */
-  if (specified)
-    {
-      value = _gtk_css_value_compute (specified, id, provider, (GtkCssStyle *)style, parent_style);
-    }
-  else if (parent_style && _gtk_css_style_property_is_inherit (_gtk_css_style_property_lookup_by_id (id)))
-    {
-      /* Just take the style from the parent */
-      value = _gtk_css_value_ref (gtk_css_style_get_value (parent_style, id));
-    }
-  else
-    {
-      value = _gtk_css_initial_value_new_compute (id, provider, (GtkCssStyle *)style, parent_style);
-    }
-
-  gtk_css_static_style_set_value (style, id, value, section);
-}
-
 GtkCssChange
 gtk_css_static_style_get_change (GtkCssStaticStyle *style)
 {
diff --git a/gtk/gtkcssstaticstyleprivate.h b/gtk/gtkcssstaticstyleprivate.h
index 81c97bbdc0..b01c0dbaed 100644
--- a/gtk/gtkcssstaticstyleprivate.h
+++ b/gtk/gtkcssstaticstyleprivate.h
@@ -56,14 +56,6 @@ GtkCssStyle *           gtk_css_static_style_new_compute        (GtkStyleProvide
                                                                  const GtkCssMatcher    *matcher,
                                                                  GtkCssStyle            *parent,
                                                                  GtkCssChange            change);
-
-void                    gtk_css_static_style_compute_value      (GtkCssStaticStyle      *style,
-                                                                 GtkStyleProvider       *provider,
-                                                                 GtkCssStyle            *parent_style,
-                                                                 guint                   id,
-                                                                 GtkCssValue            *specified,
-                                                                 GtkCssSection          *section);
-
 GtkCssChange            gtk_css_static_style_get_change         (GtkCssStaticStyle      *style);
 
 G_END_DECLS
diff --git a/gtk/gtkcssstylepropertyimpl.c b/gtk/gtkcssstylepropertyimpl.c
index ce076944d5..2b346d4a26 100644
--- a/gtk/gtkcssstylepropertyimpl.c
+++ b/gtk/gtkcssstylepropertyimpl.c
@@ -66,6 +66,8 @@ typedef enum {
   GTK_STYLE_PROPERTY_ANIMATED = (1 << 1),
 } GtkStylePropertyFlags;
 
+gboolean inherit_properties[ GTK_CSS_PROPERTY_N_PROPERTIES];
+
 static void
 gtk_css_style_property_register (const char *                   name,
                                  guint                          expected_id,
@@ -96,6 +98,8 @@ gtk_css_style_property_register (const char *                   name,
 
   _gtk_css_value_unref (initial_value);
 
+  inherit_properties[expected_id] = (flags & GTK_STYLE_PROPERTY_INHERIT) ? TRUE : FALSE;
+
   g_assert (_gtk_css_style_property_get_id (node) == expected_id);
 }
 
@@ -924,6 +928,7 @@ icon_theme_value_parse (GtkCssStyleProperty *property,
 G_STATIC_ASSERT (GTK_CSS_PROPERTY_COLOR == 0);
 G_STATIC_ASSERT (GTK_CSS_PROPERTY_DPI < GTK_CSS_PROPERTY_FONT_SIZE);
 
+
 void
 _gtk_css_style_property_init_properties (void)
 {
@@ -1720,4 +1725,5 @@ _gtk_css_style_property_init_properties (void)
                                           parse_font_variation_settings,
                                           NULL,
                                           gtk_css_font_variations_value_new_default ());
+
 }
diff --git a/gtk/gtkcssstylepropertyprivate.h b/gtk/gtkcssstylepropertyprivate.h
index 005ada4e70..f089c09995 100644
--- a/gtk/gtkcssstylepropertyprivate.h
+++ b/gtk/gtkcssstylepropertyprivate.h
@@ -80,6 +80,13 @@ void                    _gtk_css_style_property_print_value     (GtkCssStyleProp
                                                                  GtkCssValue            *value,
                                                                  GString                *string);
 
+extern gboolean inherit_properties[];
+
+inline gboolean         gtk_css_style_property_is_inherit (uint id)
+{
+  return inherit_properties[id];
+}
+
 /* XXX - find a better place for these */
 GtkCssValue * gtk_css_font_family_value_parse (GtkCssParser *parser);
 GtkCssValue * gtk_css_font_size_value_parse   (GtkCssParser *parser);


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