[gtk+] cssnode: Split out the style cache



commit 5d562b6a2aca6c1d0db93286eb7eb719fe2e3c98
Author: Benjamin Otte <otte redhat com>
Date:   Fri Jan 15 23:27:51 2016 +0100

    cssnode: Split out the style cache
    
    For now, the split out style cache doesn't cache anything. This is
    mostly to make sure that bisections of wrong caching behavior will
    bisect down to the commit that actually adds caching.

 gtk/Makefile.am                   |    2 +
 gtk/gtkcssnode.c                  |  123 ++++++++-----------------------------
 gtk/gtkcssnodeprivate.h           |    2 +
 gtk/gtkcssnodestylecache.c        |   76 +++++++++++++++++++++++
 gtk/gtkcssnodestylecacheprivate.h |   44 +++++++++++++
 5 files changed, 151 insertions(+), 96 deletions(-)
---
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index 120e245..516f1bb 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -416,6 +416,7 @@ gtk_private_h_sources =             \
        gtkcssmatcherprivate.h  \
        gtkcssnodeprivate.h             \
        gtkcssnodedeclarationprivate.h  \
+       gtkcssnodestylecacheprivate.h   \
        gtkcssnumbervalueprivate.h      \
        gtkcsspalettevalueprivate.h     \
        gtkcssparserprivate.h   \
@@ -676,6 +677,7 @@ gtk_base_c_sources =                \
        gtkcssmatcher.c         \
        gtkcssnode.c            \
        gtkcssnodedeclaration.c \
+       gtkcssnodestylecache.c  \
        gtkcssnumbervalue.c     \
        gtkcsspalettevalue.c    \
        gtkcssparser.c          \
diff --git a/gtk/gtkcssnode.c b/gtk/gtkcssnode.c
index a5dda31..1106bdb 100644
--- a/gtk/gtkcssnode.c
+++ b/gtk/gtkcssnode.c
@@ -20,13 +20,13 @@
 #include "gtkcssnodeprivate.h"
 
 #include "gtkcssanimatedstyleprivate.h"
+#include "gtkcsssectionprivate.h"
+#include "gtkcssstylepropertyprivate.h"
 #include "gtkdebug.h"
 #include "gtkintl.h"
 #include "gtkmarshalers.h"
 #include "gtksettingsprivate.h"
 #include "gtktypebuiltins.h"
-#include "gtkcssstylepropertyprivate.h"
-#include "gtkcsssectionprivate.h"
 
 /*
  * CSS nodes are the backbone of the GtkStyleContext implementation and
@@ -116,8 +116,6 @@ struct _GtkCssNodeStyleChange {
 static guint cssnode_signals[LAST_SIGNAL] = { 0 };
 static GParamSpec *cssnode_properties[NUM_PROPERTIES];
 
-static GQuark quark_global_cache;
-
 static GtkStyleProviderPrivate *
 gtk_css_node_get_style_provider_or_null (GtkCssNode *cssnode)
 {
@@ -285,10 +283,6 @@ gtk_css_node_is_last_child (GtkCssNode *node)
   return TRUE;
 }
 
-#define UNPACK_DECLARATION(packed) ((GtkCssNodeDeclaration *) (GPOINTER_TO_SIZE (packed) & ~0x3))
-#define UNPACK_FLAGS(packed) (GPOINTER_TO_SIZE (packed) & 0x3)
-#define PACK(decl, first_child, last_child) GSIZE_TO_POINTER (GPOINTER_TO_SIZE (decl) | ((first_child) ? 0x2 
: 0) | ((last_child) ? 0x1 : 0))
-
 static gboolean
 may_use_global_parent_cache (GtkCssNode *node)
 {
@@ -308,109 +302,52 @@ may_use_global_parent_cache (GtkCssNode *node)
 
 static GtkCssStyle *
 lookup_in_global_parent_cache (GtkCssNode                  *node,
-                               GtkCssStyle                 *parent,
                                const GtkCssNodeDeclaration *decl)
 {
-  GHashTable *cache;
-  GtkCssStyle *style;
+  GtkCssNode *parent;
+
+  parent = node->parent;
 
   if (parent == NULL ||
       !may_use_global_parent_cache (node))
     return NULL;
 
-  cache = g_object_get_qdata (G_OBJECT (parent), quark_global_cache);
-  if (cache == NULL)
+  if (parent->cache == NULL)
     return NULL;
 
-  style = g_hash_table_lookup (cache,
-                               PACK (decl,
-                                     gtk_css_node_is_first_child (node),
-                                     gtk_css_node_is_last_child (node)));
-
-  return style;
-}
-
-static gboolean
-may_be_stored_in_parent_cache (GtkCssStyle *style)
-{
-  GtkCssChange change;
-
-  change = gtk_css_static_style_get_change (GTK_CSS_STATIC_STYLE (style));
-
-  /* The cache is shared between all children of the parent, so if a
-   * style depends on a sibling it is not independant of the child.
-   */
-  if (change & GTK_CSS_CHANGE_ANY_SIBLING)
-    return FALSE;
-
-  /* Again, the cache is shared between all children of the parent.
-   * If the position is relevant, no child has the same style.
-   */
-  if (change & (GTK_CSS_CHANGE_NTH_CHILD | GTK_CSS_CHANGE_NTH_LAST_CHILD))
-    return FALSE;
-
-  return TRUE;
-}
-
-static guint
-gtk_global_parent_cache_hash (gconstpointer item)
-{
-  return gtk_css_node_declaration_hash (UNPACK_DECLARATION (item)) << 2
-    | UNPACK_FLAGS (item);
-}
-
-static gboolean
-gtk_global_parent_cache_equal (gconstpointer item1,
-                               gconstpointer item2)
-{
-  if (UNPACK_FLAGS (item1) != UNPACK_FLAGS (item2))
-    return FALSE;
-
-  return gtk_css_node_declaration_equal (UNPACK_DECLARATION (item1),
-                                         UNPACK_DECLARATION (item2));
-}
+  node->cache = gtk_css_node_style_cache_lookup (parent->cache,
+                                                 (GtkCssNodeDeclaration *) decl,
+                                                 gtk_css_node_is_first_child (node),
+                                                 gtk_css_node_is_last_child (node));
+  if (node->cache == NULL)
+    return NULL;
 
-static void
-gtk_global_parent_cache_free (gpointer item)
-{
-  gtk_css_node_declaration_unref (UNPACK_DECLARATION (item));
+  return gtk_css_node_style_cache_get_style (node->cache);
 }
 
 static void
 store_in_global_parent_cache (GtkCssNode                  *node,
-                              GtkCssStyle                 *parent,
                               const GtkCssNodeDeclaration *decl,
                               GtkCssStyle                 *style)
 {
-  GHashTable *cache;
+  GtkCssNode *parent;
 
   g_assert (GTK_IS_CSS_STATIC_STYLE (style));
 
+  parent = node->parent;
+
   if (parent == NULL ||
       !may_use_global_parent_cache (node))
     return;
 
-  if (!may_be_stored_in_parent_cache (style))
-    return;
-
-  cache = g_object_get_qdata (G_OBJECT (parent), quark_global_cache);
-  if (cache == NULL)
-    {
-      cache = g_hash_table_new_full (gtk_global_parent_cache_hash,
-                                     gtk_global_parent_cache_equal,
-                                     gtk_global_parent_cache_free,
-                                     g_object_unref);
-      g_object_set_qdata_full (G_OBJECT (parent),
-                               quark_global_cache,
-                               cache,
-                               (GDestroyNotify) g_hash_table_destroy);
-    }
+  if (parent->cache == NULL)
+    parent->cache = gtk_css_node_style_cache_new (parent->style);
 
-  g_hash_table_insert (cache,
-                       PACK (gtk_css_node_declaration_ref ((GtkCssNodeDeclaration *) decl),
-                             gtk_css_node_is_first_child (node),
-                             gtk_css_node_is_last_child (node)),
-                       g_object_ref (style));
+  node->cache = gtk_css_node_style_cache_insert (parent->cache,
+                                                 (GtkCssNodeDeclaration *) decl,
+                                                 gtk_css_node_is_first_child (node),
+                                                 gtk_css_node_is_last_child (node),
+                                                 style);
 }
 
 static GtkCssStyle *
@@ -424,7 +361,7 @@ gtk_css_node_create_style (GtkCssNode *cssnode)
   decl = gtk_css_node_get_declaration (cssnode);
   parent = cssnode->parent ? cssnode->parent->style : NULL;
 
-  style = lookup_in_global_parent_cache (cssnode, parent, decl);
+  style = lookup_in_global_parent_cache (cssnode, decl);
   if (style)
     return g_object_ref (style);
 
@@ -437,7 +374,7 @@ gtk_css_node_create_style (GtkCssNode *cssnode)
                                               NULL,
                                               parent);
 
-  store_in_global_parent_cache (cssnode, parent, decl, style);
+  store_in_global_parent_cache (cssnode, decl, style);
 
   return style;
 }
@@ -625,8 +562,6 @@ gtk_css_node_class_init (GtkCssNodeClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
-  quark_global_cache = g_quark_from_static_string ("gtk-global-cache");
-
   object_class->get_property = gtk_css_node_get_property;
   object_class->set_property = gtk_css_node_set_property;
   object_class->dispose = gtk_css_node_dispose;
@@ -1059,6 +994,8 @@ gtk_css_node_ensure_style (GtkCssNode *cssnode,
       if (cssnode->previous_sibling)
         gtk_css_node_ensure_style (cssnode->previous_sibling, current_time);
 
+      g_clear_pointer (&cssnode->cache, gtk_css_node_style_cache_unref);
+
       new_style = GTK_CSS_NODE_GET_CLASS (cssnode)->update_style (cssnode,
                                                                   cssnode->pending_changes,
                                                                   current_time,
@@ -1066,12 +1003,6 @@ gtk_css_node_ensure_style (GtkCssNode *cssnode,
 
       style_changed = gtk_css_node_set_style (cssnode, new_style);
       g_object_unref (new_style);
-
-      if (!style_changed && (cssnode->pending_changes & GTK_CSS_CHANGE_SOURCE))
-        {
-          /* clear the global cache if we reuse the same style after the CSS changed */
-          g_object_set_qdata (G_OBJECT (cssnode->style), quark_global_cache, NULL);
-        }
     }
   else
     {
diff --git a/gtk/gtkcssnodeprivate.h b/gtk/gtkcssnodeprivate.h
index 065b8e7..51d6cea 100644
--- a/gtk/gtkcssnodeprivate.h
+++ b/gtk/gtkcssnodeprivate.h
@@ -19,6 +19,7 @@
 #define __GTK_CSS_NODE_PRIVATE_H__
 
 #include "gtkcssnodedeclarationprivate.h"
+#include "gtkcssnodestylecacheprivate.h"
 #include "gtkcssstylechangeprivate.h"
 #include "gtkbitmaskprivate.h"
 #include "gtkcsstypesprivate.h"
@@ -46,6 +47,7 @@ struct _GtkCssNode
 
   GtkCssNodeDeclaration *decl;
   GtkCssStyle           *style;
+  GtkCssNodeStyleCache  *cache;                 /* cache for children to look up styles */
 
   GtkCssChange           pending_changes;       /* changes that accumulated since the style was last 
computed */
 
diff --git a/gtk/gtkcssnodestylecache.c b/gtk/gtkcssnodestylecache.c
new file mode 100644
index 0000000..5c4e61d
--- /dev/null
+++ b/gtk/gtkcssnodestylecache.c
@@ -0,0 +1,76 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2015 Benjamin Otte <otte gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "gtkcssnodestylecacheprivate.h"
+
+struct _GtkCssNodeStyleCache {
+  guint        ref_count;
+  GtkCssStyle *style;
+  GHashTable  *children;
+};
+
+GtkCssNodeStyleCache *
+gtk_css_node_style_cache_new (GtkCssStyle *style)
+{
+  GtkCssNodeStyleCache *result;
+
+  result = g_slice_new0 (GtkCssNodeStyleCache);
+
+  result->ref_count = 1;
+  result->style = g_object_ref (style);
+
+  return result;
+}
+
+void
+gtk_css_node_style_cache_unref (GtkCssNodeStyleCache *cache)
+{
+  cache->ref_count--; 
+
+  if (cache->ref_count > 0)
+    return;
+
+  g_object_unref (cache->style);
+}
+
+GtkCssStyle *
+gtk_css_node_style_cache_get_style (GtkCssNodeStyleCache *cache)
+{
+  return cache->style;
+}
+
+GtkCssNodeStyleCache *
+gtk_css_node_style_cache_insert (GtkCssNodeStyleCache   *parent,
+                                 GtkCssNodeDeclaration  *decl,
+                                 gboolean                is_first,
+                                 gboolean                is_last,
+                                 GtkCssStyle            *style)
+{
+  return gtk_css_node_style_cache_new (style);
+}
+
+GtkCssNodeStyleCache *
+gtk_css_node_style_cache_lookup (GtkCssNodeStyleCache   *parent,
+                                 GtkCssNodeDeclaration  *decl,
+                                 gboolean                is_first,
+                                 gboolean                is_last)
+{
+  return NULL;
+}
+
diff --git a/gtk/gtkcssnodestylecacheprivate.h b/gtk/gtkcssnodestylecacheprivate.h
new file mode 100644
index 0000000..c406fbf
--- /dev/null
+++ b/gtk/gtkcssnodestylecacheprivate.h
@@ -0,0 +1,44 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2016 Benjamin Otte <otte gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GTK_CSS_NODE_STYLE_CACHE_PRIVATE_H__
+#define __GTK_CSS_NODE_STYLE_CACHE_PRIVATE_H__
+
+#include "gtkcssstyleprivate.h"
+
+G_BEGIN_DECLS
+
+typedef struct _GtkCssNodeStyleCache GtkCssNodeStyleCache;
+
+GtkCssNodeStyleCache *  gtk_css_node_style_cache_new            (GtkCssStyle            *style);
+void                    gtk_css_node_style_cache_unref          (GtkCssNodeStyleCache   *cache);
+
+GtkCssStyle *           gtk_css_node_style_cache_get_style      (GtkCssNodeStyleCache   *cache);
+
+GtkCssNodeStyleCache *  gtk_css_node_style_cache_insert         (GtkCssNodeStyleCache   *parent,
+                                                                 GtkCssNodeDeclaration  *decl,
+                                                                 gboolean                is_first,
+                                                                 gboolean                is_last,
+                                                                 GtkCssStyle            *style);
+GtkCssNodeStyleCache *  gtk_css_node_style_cache_lookup         (GtkCssNodeStyleCache   *parent,
+                                                                 GtkCssNodeDeclaration  *decl,
+                                                                 gboolean                is_first,
+                                                                 gboolean                is_last);
+
+G_END_DECLS
+
+#endif /* __GTK_CSS_NODE_STYLE_CACHE_PRIVATE_H__ */


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