From a1ee2b7b82154a506f6dee546975ed97a5fc9e2a Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Mon, 10 Dec 2012 12:57:10 +0100 Subject: [PATCH] css: Speed up name matching 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 | 2 +- gtk/gtkcssmatcher.c | 24 +++++------ gtk/gtkcssmatcherprivate.h | 10 ++--- gtk/gtkcssselector.c | 86 +++++++++++++++++++++++++++++++++----- 4 files changed, 93 insertions(+), 29 deletions(-) diff --git a/configure.ac b/configure.ac index d0813868a..0e22d061d 100644 --- a/configure.ac +++ b/configure.ac @@ -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]) diff --git a/gtk/gtkcssmatcher.c b/gtk/gtkcssmatcher.c index 68207387f..ccdf5479c 100644 --- a/gtk/gtkcssmatcher.c +++ b/gtk/gtkcssmatcher.c @@ -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, diff --git a/gtk/gtkcssmatcherprivate.h b/gtk/gtkcssmatcherprivate.h index 28810b2ca..1b2108c38 100644 --- a/gtk/gtkcssmatcherprivate.h +++ b/gtk/gtkcssmatcherprivate.h @@ -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 diff --git a/gtk/gtkcssselector.c b/gtk/gtkcssselector.c index 718131be0..fcf0ac6cd 100644 --- a/gtk/gtkcssselector.c +++ b/gtk/gtkcssselector.c @@ -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) - ? >K_CSS_SELECTOR_REGION - : >K_CSS_SELECTOR_NAME, - selector, - g_intern_string (name)); + if (_gtk_style_context_check_region_name (name)) + selector = gtk_css_selector_new (>K_CSS_SELECTOR_REGION, + selector, + g_intern_string (name)); + else + selector = gtk_css_selector_new (>K_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; -- 2.43.2