]> Pileus Git - ~andy/gtk/commitdiff
css: Speed up name matching
authorAlexander Larsson <alexl@redhat.com>
Mon, 10 Dec 2012 11:57:10 +0000 (12:57 +0100)
committerAlexander Larsson <alexl@redhat.com>
Mon, 10 Dec 2012 11:57:10 +0000 (12:57 +0100)
We use the new g_type_get_type_registration_serial() so that we can
cache and properly invalidate the result of g_type_from_name().

This bumps the glib requirement to 2.35.3 to get the new function.

https://bugzilla.gnome.org/show_bug.cgi?id=689847

configure.ac
gtk/gtkcssmatcher.c
gtk/gtkcssmatcherprivate.h
gtk/gtkcssselector.c

index d0813868a3fe8d833c45654c922fdf61487e0571..0e22d061dff8877719622075f93330ceccfb918b 100644 (file)
@@ -39,7 +39,7 @@ AC_CONFIG_AUX_DIR([build-aux])
 m4_define([gtk_binary_version], [3.0.0])
 
 # required versions of other packages
-m4_define([glib_required_version], [2.35.0])
+m4_define([glib_required_version], [2.35.3])
 m4_define([pango_required_version], [1.32.4])
 m4_define([atk_required_version], [2.5.3])
 m4_define([cairo_required_version], [1.10.0])
index 68207387fef8f729726b16707001c8f854e4a989..ccdf5479cf853575e5e1fd3615a05c09f9a8b0e9 100644 (file)
@@ -62,13 +62,11 @@ gtk_css_matcher_widget_path_get_state (const GtkCssMatcher *matcher)
 }
 
 static gboolean
-gtk_css_matcher_widget_path_has_name (const GtkCssMatcher *matcher,
-                                      const char          *name)
+gtk_css_matcher_widget_path_has_type (const GtkCssMatcher *matcher,
+                                      GType                type)
 {
   const GtkWidgetPath *siblings;
-  GType type;
-  
-  type = g_type_from_name (name);
+
   siblings = gtk_widget_path_iter_get_siblings (matcher->path.path, matcher->path.index);
   if (siblings && matcher->path.sibling_index != gtk_widget_path_iter_get_sibling_index (matcher->path.path, matcher->path.index))
     return g_type_is_a (gtk_widget_path_iter_get_object_type (siblings, matcher->path.sibling_index), type);
@@ -179,7 +177,7 @@ static const GtkCssMatcherClass GTK_CSS_MATCHER_WIDGET_PATH = {
   gtk_css_matcher_widget_path_get_parent,
   gtk_css_matcher_widget_path_get_previous,
   gtk_css_matcher_widget_path_get_state,
-  gtk_css_matcher_widget_path_has_name,
+  gtk_css_matcher_widget_path_has_type,
   gtk_css_matcher_widget_path_has_class,
   gtk_css_matcher_widget_path_has_id,
   gtk_css_matcher_widget_path_has_regions,
@@ -236,8 +234,8 @@ gtk_css_matcher_any_get_state (const GtkCssMatcher *matcher)
 }
 
 static gboolean
-gtk_css_matcher_any_has_name (const GtkCssMatcher *matcher,
-                              const char          *name)
+gtk_css_matcher_any_has_type (const GtkCssMatcher *matcher,
+                              GType                type)
 {
   return TRUE;
 }
@@ -283,7 +281,7 @@ static const GtkCssMatcherClass GTK_CSS_MATCHER_ANY = {
   gtk_css_matcher_any_get_parent,
   gtk_css_matcher_any_get_previous,
   gtk_css_matcher_any_get_state,
-  gtk_css_matcher_any_has_name,
+  gtk_css_matcher_any_has_type,
   gtk_css_matcher_any_has_class,
   gtk_css_matcher_any_has_id,
   gtk_css_matcher_any_has_regions,
@@ -332,11 +330,11 @@ gtk_css_matcher_superset_get_state (const GtkCssMatcher *matcher)
 }
 
 static gboolean
-gtk_css_matcher_superset_has_name (const GtkCssMatcher *matcher,
-                                   const char          *name)
+gtk_css_matcher_superset_has_type (const GtkCssMatcher *matcher,
+                                   GType                type)
 {
   if (matcher->superset.relevant & GTK_CSS_CHANGE_NAME)
-    return _gtk_css_matcher_has_name (matcher->superset.subset, name);
+    return _gtk_css_matcher_has_type (matcher->superset.subset, type);
   else
     return TRUE;
 }
@@ -402,7 +400,7 @@ static const GtkCssMatcherClass GTK_CSS_MATCHER_SUPERSET = {
   gtk_css_matcher_superset_get_parent,
   gtk_css_matcher_superset_get_previous,
   gtk_css_matcher_superset_get_state,
-  gtk_css_matcher_superset_has_name,
+  gtk_css_matcher_superset_has_type,
   gtk_css_matcher_superset_has_class,
   gtk_css_matcher_superset_has_id,
   gtk_css_matcher_superset_has_regions,
index 28810b2ca304fe4a4a9dc924a780055543f309e7..1b2108c3870b5f9ef04c830f4eaa89c6a7b7766f 100644 (file)
@@ -36,8 +36,8 @@ struct _GtkCssMatcherClass {
                                                    const GtkCssMatcher    *next);
 
   GtkStateFlags   (* get_state)                   (const GtkCssMatcher   *matcher);
-  gboolean        (* has_name)                    (const GtkCssMatcher   *matcher,
-                                                   const char            *name);
+  gboolean        (* has_type)                    (const GtkCssMatcher   *matcher,
+                                                   GType                  type);
   gboolean        (* has_class)                   (const GtkCssMatcher   *matcher,
                                                    GQuark                 class_name);
   gboolean        (* has_id)                      (const GtkCssMatcher   *matcher,
@@ -103,10 +103,10 @@ _gtk_css_matcher_get_state (const GtkCssMatcher *matcher)
 }
 
 static inline gboolean
-_gtk_css_matcher_has_name (const GtkCssMatcher *matcher,
-                           const char          *name)
+_gtk_css_matcher_has_type (const GtkCssMatcher *matcher,
+                           GType type)
 {
-  return matcher->klass->has_name (matcher, name);
+  return matcher->klass->has_type (matcher, type);
 }
 
 static inline gboolean
index 718131be033032c118bf0359cbb5286986dfa94e..fcf0ac6cdfe32f793eea5bf34f77652632f0c499 100644 (file)
@@ -682,18 +682,74 @@ static const GtkCssSelectorClass GTK_CSS_SELECTOR_ANY = {
 
 /* NAME */
 
+typedef struct {
+  GType type;
+  const char *name;
+} TypeReference;
+
+static GHashTable *type_refs_ht = NULL;
+static guint type_refs_last_serial = 0;
+
+static TypeReference *
+get_type_reference (const char *name)
+{
+  TypeReference *ref;
+
+
+  if (type_refs_ht == NULL)
+    type_refs_ht = g_hash_table_new (g_str_hash, g_str_equal);
+
+  ref = g_hash_table_lookup (type_refs_ht, name);
+
+  if (ref != NULL)
+    return ref;
+
+  ref = g_slice_new (TypeReference);
+  ref->name = g_intern_string (name);
+  ref->type = g_type_from_name (ref->name);
+
+  g_hash_table_insert (type_refs_ht,
+                      (gpointer)ref->name, ref);
+
+  return ref;
+}
+
+static void
+update_type_references (void)
+{
+  GHashTableIter iter;
+  guint serial;
+  gpointer value;
+
+  serial = g_type_get_type_registration_serial ();
+
+  if (serial == type_refs_last_serial)
+    return;
+
+  type_refs_last_serial = serial;
+
+  g_hash_table_iter_init (&iter, type_refs_ht);
+  while (g_hash_table_iter_next (&iter,
+                                NULL, &value))
+    {
+      TypeReference *ref = value;
+      if (ref->type == G_TYPE_INVALID)
+       ref->type = g_type_from_name (ref->name);
+    }
+}
+
 static void
 gtk_css_selector_name_print (const GtkCssSelector *selector,
                              GString              *string)
 {
-  g_string_append (string, selector->data);
+  g_string_append (string, ((TypeReference *)selector->data)->name);
 }
 
 static gboolean
 gtk_css_selector_name_match (const GtkCssSelector *selector,
                              const GtkCssMatcher  *matcher)
 {
-  if (!_gtk_css_matcher_has_name (matcher, selector->data))
+  if (!_gtk_css_matcher_has_type (matcher, ((TypeReference *)selector->data)->type))
     return FALSE;
 
   return gtk_css_selector_match (gtk_css_selector_previous (selector), matcher);
@@ -704,7 +760,7 @@ gtk_css_selector_name_tree_match (const GtkCssSelectorTree *tree,
                                  const GtkCssMatcher  *matcher,
                                  GHashTable *res)
 {
-  if (!_gtk_css_matcher_has_name (matcher, tree->selector.data))
+  if (!_gtk_css_matcher_has_type (matcher, ((TypeReference *)tree->selector.data)->type))
     return;
 
   gtk_css_selector_tree_found_match (tree, res);
@@ -718,7 +774,7 @@ gtk_css_selector_name_tree_get_change (const GtkCssSelectorTree *tree,
 {
   GtkCssChange change, previous_change;
 
-  if (!_gtk_css_matcher_has_name (matcher, tree->selector.data))
+  if (!_gtk_css_matcher_has_type (matcher, ((TypeReference *)tree->selector.data)->type))
     return 0;
 
   change = 0;
@@ -745,7 +801,8 @@ static int
 gtk_css_selector_name_compare_one (const GtkCssSelector *a,
                                   const GtkCssSelector *b)
 {
-  return strcmp (a->data, b->data);
+  return strcmp (((TypeReference *)a->data)->name,
+                ((TypeReference *)b->data)->name);
 }
 
 static const GtkCssSelectorClass GTK_CSS_SELECTOR_NAME = {
@@ -1805,11 +1862,14 @@ try_parse_name (GtkCssParser   *parser,
   name = _gtk_css_parser_try_ident (parser, FALSE);
   if (name)
     {
-      selector = gtk_css_selector_new (_gtk_style_context_check_region_name (name)
-                                       ? &GTK_CSS_SELECTOR_REGION
-                                       : &GTK_CSS_SELECTOR_NAME,
-                                       selector,
-                                       g_intern_string (name));
+      if (_gtk_style_context_check_region_name (name))
+       selector = gtk_css_selector_new (&GTK_CSS_SELECTOR_REGION,
+                                        selector,
+                                        g_intern_string (name));
+      else
+       selector = gtk_css_selector_new (&GTK_CSS_SELECTOR_NAME,
+                                        selector,
+                                        get_type_reference (name));
       g_free (name);
     }
   else if (_gtk_css_parser_try (parser, "*", FALSE))
@@ -1916,6 +1976,8 @@ _gtk_css_selector_tree_match_get_change (const GtkCssSelectorTree *tree)
 {
   GtkCssChange change = 0;
 
+  update_type_references ();
+
   while (tree)
     {
       change = tree->selector.class->get_change (&tree->selector, change);
@@ -1947,6 +2009,8 @@ _gtk_css_selector_matches (const GtkCssSelector *selector,
   g_return_val_if_fail (selector != NULL, FALSE);
   g_return_val_if_fail (matcher != NULL, FALSE);
 
+  update_type_references ();
+
   return gtk_css_selector_match (selector, matcher);
 }
 
@@ -2085,6 +2149,8 @@ _gtk_css_selector_tree_match_all (const GtkCssSelectorTree *tree,
   GHashTableIter iter;
   gpointer key;
 
+  update_type_references ();
+
   res = g_hash_table_new (g_direct_hash, g_direct_equal);
 
   for (; tree != NULL;