From e833f686bb246d02dda9096653214ba657f460ba Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Fri, 6 Oct 2017 13:15:23 +0000 Subject: [PATCH] [C++ PATCH] use hash-table for namespace contents https://gcc.gnu.org/ml/gcc-patches/2017-10/msg00365.html Use hash_table for namespace bindings * cp-tree.h (struct named_decl_hash): New. (lang_decl_ns): Change type of bindings field. * lex.c (maybe_add_lang_decl_raw): Adjust. * name-lookup.c (find_namespace_slot): Adjust. (do_pushdecl): Push NULL-named namespace. (do_push_nested_namespace): Adjust. (push_namespace): Push anonymous namespace as NULL name. From-SVN: r253489 --- gcc/cp/ChangeLog | 12 ++++++++++++ gcc/cp/cp-tree.h | 41 +++++++++++++++++++++++++++++++++++++---- gcc/cp/lex.c | 2 +- gcc/cp/name-lookup.c | 36 ++++++++++++------------------------ 4 files changed, 62 insertions(+), 29 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index c5c28f4..ef053a5 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,17 @@ +2017-10-06 Nathan Sidwell + + Use hash_table for namespace bindings + * cp-tree.h (struct named_decl_hash): New. + (lang_decl_ns): Change type of bindings field. + * lex.c (maybe_add_lang_decl_raw): Adjust. + * name-lookup.c (find_namespace_slot): Adjust. + (do_pushdecl): Push NULL-named namespace. + (do_push_nested_namespace): Adjust. + (push_namespace): Push anonymous namespace as NULL name. + 2017-10-05 Jason Merrill + Pass variadic class objects exactly like named by-value args. * call.c (convert_arg_to_ellipsis): Use the result of force_rvalue. 2017-10-05 Nathan Sidwell diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 8445bfae..cac5f3d 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -828,6 +828,25 @@ class lkp_iterator : public ovl_iterator } }; +/* hash traits for declarations. Hashes potential overload sets via + DECL_NAME. */ + +struct named_decl_hash : ggc_remove +{ + typedef tree value_type; /* A DECL or OVERLOAD */ + typedef tree compare_type; /* An identifier. */ + + inline static hashval_t hash (const value_type decl); + inline static bool equal (const value_type existing, compare_type candidate); + + static inline void mark_empty (value_type &p) {p = NULL_TREE;} + static inline bool is_empty (value_type p) {return !p;} + + /* Nothing is deletable. Everything is insertable. */ + static bool is_deleted (value_type) { return false; } + static void mark_deleted (value_type) { gcc_unreachable (); } +}; + struct GTY(()) tree_template_decl { struct tree_decl_common common; tree arguments; @@ -2548,10 +2567,10 @@ struct GTY(()) lang_decl_ns { vec *usings; vec *inlinees; - /* Map from IDENTIFIER nodes to DECLS. It'd be nice to have this - inline, but as the hash_map has a dtor, we can't then put this - struct into a union (until moving to c++11). */ - hash_map *bindings; + /* Hash table of bound decls. It'd be nice to have this inline, but + as the hash_map has a dtor, we can't then put this struct into a + union (until moving to c++11). */ + hash_table *bindings; }; /* DECL_LANG_SPECIFIC for parameters. */ @@ -7370,6 +7389,20 @@ type_unknown_p (const_tree expr) return TREE_TYPE (expr) == unknown_type_node; } +inline hashval_t +named_decl_hash::hash (const value_type decl) +{ + tree name = OVL_NAME (decl); + return name ? IDENTIFIER_HASH_VALUE (name) : 0; +} + +inline bool +named_decl_hash::equal (const value_type existing, compare_type candidate) +{ + tree name = OVL_NAME (existing); + return candidate == name; +} + /* -- end of C++ */ #endif /* ! GCC_CP_TREE_H */ diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index 5bdea7b..fd93401 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -651,7 +651,7 @@ maybe_add_lang_decl_raw (tree t, bool decomp_p) if (sel == lds_ns) /* Who'd create a namespace, only to put nothing in it? */ - ld->u.ns.bindings = hash_map::create_ggc (499); + ld->u.ns.bindings = hash_table::create_ggc (499); if (GATHER_STATISTICS) { diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index a20c603..84f7381 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -86,17 +86,9 @@ create_local_binding (cp_binding_level *level, tree name) static tree * find_namespace_slot (tree ns, tree name, bool create_p = false) { - tree *slot; - - if (create_p) - { - bool existed; - slot = &DECL_NAMESPACE_BINDINGS (ns)->get_or_insert (name, &existed); - if (!existed) - *slot = NULL_TREE; - } - else - slot = DECL_NAMESPACE_BINDINGS (ns)->get (name); + tree *slot = DECL_NAMESPACE_BINDINGS (ns) + ->find_slot_with_hash (name, name ? IDENTIFIER_HASH_VALUE (name) : 0, + create_p ? INSERT : NO_INSERT); return slot; } @@ -2950,7 +2942,10 @@ do_pushdecl (tree decl, bool is_friend) while (level->kind == sk_class) level = level->level_chain; - if (tree name = DECL_NAME (decl)) + /* An anonymous namespace has a NULL DECL_NAME, but we still want to + insert it. Other NULL-named decls, not so much. */ + tree name = DECL_NAME (decl); + if (name || TREE_CODE (decl) == NAMESPACE_DECL) { cxx_binding *binding = NULL; /* Local scope binding. */ tree ns = NULL_TREE; /* Searched namespace. */ @@ -6615,9 +6610,7 @@ do_push_nested_namespace (tree ns) { do_push_nested_namespace (CP_DECL_CONTEXT (ns)); gcc_checking_assert - (find_namespace_value (current_namespace, - DECL_NAME (ns) ? DECL_NAME (ns) - : anon_identifier) == ns); + (find_namespace_value (current_namespace, DECL_NAME (ns)) == ns); resume_scope (NAMESPACE_LEVEL (ns)); current_namespace = ns; } @@ -6775,10 +6768,7 @@ push_namespace (tree name, bool make_inline) /* We should not get here if the global_namespace is not yet constructed nor if NAME designates the global namespace: The global scope is constructed elsewhere. */ - gcc_assert (global_namespace != NULL && name != global_identifier); - - if (!name) - name = anon_identifier; + gcc_checking_assert (global_namespace != NULL && name != global_identifier); tree ns = NULL_TREE; { @@ -6824,11 +6814,9 @@ push_namespace (tree name, bool make_inline) ns = NULL_TREE; else { - if (name == anon_identifier) + if (!name) { - /* Clear DECL_NAME for the benefit of debugging back ends. */ - SET_DECL_ASSEMBLER_NAME (ns, name); - DECL_NAME (ns) = NULL_TREE; + SET_DECL_ASSEMBLER_NAME (ns, anon_identifier); if (!make_inline) add_using_namespace (DECL_NAMESPACE_USING (current_namespace), @@ -6843,7 +6831,7 @@ push_namespace (tree name, bool make_inline) vec_safe_push (DECL_NAMESPACE_INLINEES (current_namespace), ns); } - if (name == anon_identifier || make_inline) + if (!name || make_inline) emit_debug_info_using_namespace (current_namespace, ns, true); } } -- 2.7.4