diff mbox series

Add some hash_map_safe_* functions like vec_safe_*.

Message ID 20190930183035.7347-1-jason@redhat.com
State New
Headers show
Series Add some hash_map_safe_* functions like vec_safe_*. | expand

Commit Message

Jason Merrill Sept. 30, 2019, 6:30 p.m. UTC
gcc/
	* hash-map.h (default_size): Put in member variable.
	(create_ggc): Use it as default argument.
	(hash_map_maybe_create, hash_map_safe_get)
	(hash_map_safe_get_or_insert, hash_map_safe_put): New fns.
gcc/cp/
	* constexpr.c (maybe_initialize_fundef_copies_table): Remove.
	(get_fundef_copy): Use hash_map_safe_get_or_insert.
	* cp-objcp-common.c (cp_get_debug_type): Use hash_map_safe_*.
	* decl.c (store_decomp_type): Remove.
	(cp_finish_decomp): Use hash_map_safe_put.
	* init.c (get_nsdmi): Use hash_map_safe_*.
	* pt.c (store_defaulted_ttp, lookup_defaulted_ttp): Remove.
	(add_defaults_to_ttp): Use hash_map_safe_*.
---
 gcc/hash-map.h           | 38 ++++++++++++++++++++++++++++++++++++--
 gcc/cp/constexpr.c       | 14 ++------------
 gcc/cp/cp-objcp-common.c |  6 ++----
 gcc/cp/decl.c            |  9 +--------
 gcc/cp/init.c            |  9 ++-------
 gcc/cp/pt.c              | 21 +++------------------
 gcc/hash-table.c         |  2 +-
 7 files changed, 47 insertions(+), 52 deletions(-)


base-commit: c6fd1c4cf03b10c7ab34dea84f70c618c824599e

Comments

Jason Merrill Sept. 30, 2019, 6:32 p.m. UTC | #1
My comments accidentally got lost.

Several places in the front-end (and elsewhere) use the same lazy
allocation pattern for hash_maps, and this patch replaces them with
hash_map_safe_* functions like vec_safe_*.  They don't provide a way
to specify an initial size, but I don't think that's a significant
issue.

Tested x86_64-pc-linux-gnu.  OK for trunk?

On Mon, Sep 30, 2019 at 2:30 PM Jason Merrill <jason@redhat.com> wrote:
>
> gcc/
>         * hash-map.h (default_size): Put in member variable.
>         (create_ggc): Use it as default argument.
>         (hash_map_maybe_create, hash_map_safe_get)
>         (hash_map_safe_get_or_insert, hash_map_safe_put): New fns.
> gcc/cp/
>         * constexpr.c (maybe_initialize_fundef_copies_table): Remove.
>         (get_fundef_copy): Use hash_map_safe_get_or_insert.
>         * cp-objcp-common.c (cp_get_debug_type): Use hash_map_safe_*.
>         * decl.c (store_decomp_type): Remove.
>         (cp_finish_decomp): Use hash_map_safe_put.
>         * init.c (get_nsdmi): Use hash_map_safe_*.
>         * pt.c (store_defaulted_ttp, lookup_defaulted_ttp): Remove.
>         (add_defaults_to_ttp): Use hash_map_safe_*.
> ---
>  gcc/hash-map.h           | 38 ++++++++++++++++++++++++++++++++++++--
>  gcc/cp/constexpr.c       | 14 ++------------
>  gcc/cp/cp-objcp-common.c |  6 ++----
>  gcc/cp/decl.c            |  9 +--------
>  gcc/cp/init.c            |  9 ++-------
>  gcc/cp/pt.c              | 21 +++------------------
>  gcc/hash-table.c         |  2 +-
>  7 files changed, 47 insertions(+), 52 deletions(-)
>
> diff --git a/gcc/hash-map.h b/gcc/hash-map.h
> index ba20fe79f23..e638f761465 100644
> --- a/gcc/hash-map.h
> +++ b/gcc/hash-map.h
> @@ -128,8 +128,9 @@ class GTY((user)) hash_map
>         }
>    };
>
> +  static const size_t default_size = 13;
>  public:
> -  explicit hash_map (size_t n = 13, bool ggc = false,
> +  explicit hash_map (size_t n = default_size, bool ggc = false,
>                      bool sanitize_eq_and_hash = true,
>                      bool gather_mem_stats = GATHER_STATISTICS
>                      CXX_MEM_STAT_INFO)
> @@ -146,7 +147,7 @@ public:
>                HASH_MAP_ORIGIN PASS_MEM_STAT) {}
>
>    /* Create a hash_map in ggc memory.  */
> -  static hash_map *create_ggc (size_t size,
> +  static hash_map *create_ggc (size_t size = default_size,
>                                bool gather_mem_stats = GATHER_STATISTICS
>                                CXX_MEM_STAT_INFO)
>      {
> @@ -326,4 +327,37 @@ gt_pch_nx (hash_map<K, V, H> *h, gt_pointer_operator op, void *cookie)
>    op (&h->m_table.m_entries, cookie);
>  }
>
> +template<typename K, typename V, typename H>
> +inline hash_map<K,V,H> *
> +hash_map_maybe_create (hash_map<K,V,H> *&h)
> +{
> +  if (!h)
> +    h = h->create_ggc ();
> +  return h;
> +}
> +
> +/* Like h->get, but handles null h.  */
> +template<typename K, typename V, typename H>
> +inline V*
> +hash_map_safe_get (hash_map<K,V,H> *h, const K& k)
> +{
> +  return h ? h->get (k) : NULL;
> +}
> +
> +/* Like h->get, but handles null h.  */
> +template<typename K, typename V, typename H>
> +inline V&
> +hash_map_safe_get_or_insert (hash_map<K,V,H> *&h, const K& k, bool *e = NULL)
> +{
> +  return hash_map_maybe_create (h)->get_or_insert (k, e);
> +}
> +
> +/* Like h->put, but handles null h.  */
> +template<typename K, typename V, typename H>
> +inline bool
> +hash_map_safe_put (hash_map<K,V,H> *&h, const K& k, const V& v)
> +{
> +  return hash_map_maybe_create (h)->put (k, v);
> +}
> +
>  #endif
> diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
> index cb5484f4b72..904b70a9c99 100644
> --- a/gcc/cp/constexpr.c
> +++ b/gcc/cp/constexpr.c
> @@ -1098,15 +1098,6 @@ maybe_initialize_constexpr_call_table (void)
>
>  static GTY(()) hash_map<tree, tree> *fundef_copies_table;
>
> -/* Initialize FUNDEF_COPIES_TABLE if it's not initialized.  */
> -
> -static void
> -maybe_initialize_fundef_copies_table ()
> -{
> -  if (fundef_copies_table == NULL)
> -    fundef_copies_table = hash_map<tree,tree>::create_ggc (101);
> -}
> -
>  /* Reuse a copy or create a new unshared copy of the function FUN.
>     Return this copy.  We use a TREE_LIST whose PURPOSE is body, VALUE
>     is parms, TYPE is result.  */
> @@ -1114,11 +1105,10 @@ maybe_initialize_fundef_copies_table ()
>  static tree
>  get_fundef_copy (constexpr_fundef *fundef)
>  {
> -  maybe_initialize_fundef_copies_table ();
> -
>    tree copy;
>    bool existed;
> -  tree *slot = &fundef_copies_table->get_or_insert (fundef->decl, &existed);
> +  tree *slot = &hash_map_safe_get_or_insert (fundef_copies_table,
> +                                            fundef->decl, &existed);
>
>    if (!existed)
>      {
> diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c
> index 4369a5b5570..652b94230ad 100644
> --- a/gcc/cp/cp-objcp-common.c
> +++ b/gcc/cp/cp-objcp-common.c
> @@ -145,11 +145,9 @@ cp_get_debug_type (const_tree type)
>    if (dtype)
>      {
>        tree ktype = CONST_CAST_TREE (type);
> -      if (debug_type_map == NULL)
> -       debug_type_map = tree_cache_map::create_ggc (512);
> -      else if (tree *slot = debug_type_map->get (ktype))
> +      if (tree *slot = hash_map_safe_get (debug_type_map, ktype))
>         return *slot;
> -      debug_type_map->put (ktype, dtype);
> +      hash_map_safe_put (debug_type_map, ktype, dtype);
>      }
>
>    return dtype;
> diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
> index 67c4521e98c..562fe10bd96 100644
> --- a/gcc/cp/decl.c
> +++ b/gcc/cp/decl.c
> @@ -7704,13 +7704,6 @@ get_tuple_decomp_init (tree decl, unsigned i)
>     based on the actual type of the variable, so store it in a hash table.  */
>
>  static GTY((cache)) tree_cache_map *decomp_type_table;
> -static void
> -store_decomp_type (tree v, tree t)
> -{
> -  if (!decomp_type_table)
> -    decomp_type_table = tree_cache_map::create_ggc (13);
> -  decomp_type_table->put (v, t);
> -}
>
>  tree
>  lookup_decomp_type (tree v)
> @@ -7946,7 +7939,7 @@ cp_finish_decomp (tree decl, tree first, unsigned int count)
>               goto error_out;
>             }
>           /* Save the decltype away before reference collapse.  */
> -         store_decomp_type (v[i], eltype);
> +         hash_map_safe_put (decomp_type_table, v[i], eltype);
>           eltype = cp_build_reference_type (eltype, !lvalue_p (init));
>           TREE_TYPE (v[i]) = eltype;
>           layout_decl (v[i], 0);
> diff --git a/gcc/cp/init.c b/gcc/cp/init.c
> index 67e06568b2f..4bd60859bf8 100644
> --- a/gcc/cp/init.c
> +++ b/gcc/cp/init.c
> @@ -563,10 +563,9 @@ get_nsdmi (tree member, bool in_ctor, tsubst_flags_t complain)
>        init = DECL_INITIAL (DECL_TI_TEMPLATE (member));
>        location_t expr_loc
>         = cp_expr_loc_or_loc (init, DECL_SOURCE_LOCATION (member));
> -      tree *slot;
>        if (TREE_CODE (init) == DEFERRED_PARSE)
>         /* Unparsed.  */;
> -      else if (nsdmi_inst && (slot = nsdmi_inst->get (member)))
> +      else if (tree *slot = hash_map_safe_get (nsdmi_inst, member))
>         init = *slot;
>        /* Check recursive instantiation.  */
>        else if (DECL_INSTANTIATING_NSDMI_P (member))
> @@ -611,11 +610,7 @@ get_nsdmi (tree member, bool in_ctor, tsubst_flags_t complain)
>           DECL_INSTANTIATING_NSDMI_P (member) = 0;
>
>           if (init != error_mark_node)
> -           {
> -             if (!nsdmi_inst)
> -               nsdmi_inst = tree_cache_map::create_ggc (37);
> -             nsdmi_inst->put (member, init);
> -           }
> +           hash_map_safe_put (nsdmi_inst, member, init);
>
>           if (pushed)
>             {
> diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
> index 44b36183304..d2aeb1ccba6 100644
> --- a/gcc/cp/pt.c
> +++ b/gcc/cp/pt.c
> @@ -7357,21 +7357,6 @@ coerce_template_args_for_ttp (tree templ, tree arglist,
>  /* A cache of template template parameters with match-all default
>     arguments.  */
>  static GTY((deletable)) hash_map<tree,tree> *defaulted_ttp_cache;
> -static void
> -store_defaulted_ttp (tree v, tree t)
> -{
> -  if (!defaulted_ttp_cache)
> -    defaulted_ttp_cache = hash_map<tree,tree>::create_ggc (13);
> -  defaulted_ttp_cache->put (v, t);
> -}
> -static tree
> -lookup_defaulted_ttp (tree v)
> -{
> -  if (defaulted_ttp_cache)
> -    if (tree *p = defaulted_ttp_cache->get (v))
> -      return *p;
> -  return NULL_TREE;
> -}
>
>  /* T is a bound template template-parameter.  Copy its arguments into default
>     arguments of the template template-parameter's template parameters.  */
> @@ -7379,8 +7364,8 @@ lookup_defaulted_ttp (tree v)
>  static tree
>  add_defaults_to_ttp (tree otmpl)
>  {
> -  if (tree c = lookup_defaulted_ttp (otmpl))
> -    return c;
> +  if (tree *c = hash_map_safe_get (defaulted_ttp_cache, otmpl))
> +    return *c;
>
>    tree ntmpl = copy_node (otmpl);
>
> @@ -7410,7 +7395,7 @@ add_defaults_to_ttp (tree otmpl)
>         }
>      }
>
> -  store_defaulted_ttp (otmpl, ntmpl);
> +  hash_map_safe_put (defaulted_ttp_cache, otmpl, ntmpl);
>    return ntmpl;
>  }
>
> diff --git a/gcc/hash-table.c b/gcc/hash-table.c
> index e3b5d3da09e..3520c3bb596 100644
> --- a/gcc/hash-table.c
> +++ b/gcc/hash-table.c
> @@ -78,7 +78,7 @@ struct prime_ent const prime_tab[] = {
>  unsigned int hash_table_sanitize_eq_limit;
>
>  /* The following function returns an index into the above table of the
> -   nearest prime number which is greater than N, and near a power of two. */
> +   nearest prime number which is at least N, and near a power of two. */
>
>  unsigned int
>  hash_table_higher_prime_index (unsigned long n)
>
> base-commit: c6fd1c4cf03b10c7ab34dea84f70c618c824599e
> --
> 2.21.0
>
Richard Biener Oct. 1, 2019, 7:34 a.m. UTC | #2
On Mon, Sep 30, 2019 at 8:33 PM Jason Merrill <jason@redhat.com> wrote:
>
> My comments accidentally got lost.
>
> Several places in the front-end (and elsewhere) use the same lazy
> allocation pattern for hash_maps, and this patch replaces them with
> hash_map_safe_* functions like vec_safe_*.  They don't provide a way
> to specify an initial size, but I don't think that's a significant
> issue.
>
> Tested x86_64-pc-linux-gnu.  OK for trunk?

You are using create_ggc but the new functions do not indicate that ggc
allocation is done.  It's then also incomplete with not having a non-ggc variant
of them?  Maybe I'm missing something.

Thanks,
Richard.

> On Mon, Sep 30, 2019 at 2:30 PM Jason Merrill <jason@redhat.com> wrote:
> >
> > gcc/
> >         * hash-map.h (default_size): Put in member variable.
> >         (create_ggc): Use it as default argument.
> >         (hash_map_maybe_create, hash_map_safe_get)
> >         (hash_map_safe_get_or_insert, hash_map_safe_put): New fns.
> > gcc/cp/
> >         * constexpr.c (maybe_initialize_fundef_copies_table): Remove.
> >         (get_fundef_copy): Use hash_map_safe_get_or_insert.
> >         * cp-objcp-common.c (cp_get_debug_type): Use hash_map_safe_*.
> >         * decl.c (store_decomp_type): Remove.
> >         (cp_finish_decomp): Use hash_map_safe_put.
> >         * init.c (get_nsdmi): Use hash_map_safe_*.
> >         * pt.c (store_defaulted_ttp, lookup_defaulted_ttp): Remove.
> >         (add_defaults_to_ttp): Use hash_map_safe_*.
> > ---
> >  gcc/hash-map.h           | 38 ++++++++++++++++++++++++++++++++++++--
> >  gcc/cp/constexpr.c       | 14 ++------------
> >  gcc/cp/cp-objcp-common.c |  6 ++----
> >  gcc/cp/decl.c            |  9 +--------
> >  gcc/cp/init.c            |  9 ++-------
> >  gcc/cp/pt.c              | 21 +++------------------
> >  gcc/hash-table.c         |  2 +-
> >  7 files changed, 47 insertions(+), 52 deletions(-)
> >
> > diff --git a/gcc/hash-map.h b/gcc/hash-map.h
> > index ba20fe79f23..e638f761465 100644
> > --- a/gcc/hash-map.h
> > +++ b/gcc/hash-map.h
> > @@ -128,8 +128,9 @@ class GTY((user)) hash_map
> >         }
> >    };
> >
> > +  static const size_t default_size = 13;
> >  public:
> > -  explicit hash_map (size_t n = 13, bool ggc = false,
> > +  explicit hash_map (size_t n = default_size, bool ggc = false,
> >                      bool sanitize_eq_and_hash = true,
> >                      bool gather_mem_stats = GATHER_STATISTICS
> >                      CXX_MEM_STAT_INFO)
> > @@ -146,7 +147,7 @@ public:
> >                HASH_MAP_ORIGIN PASS_MEM_STAT) {}
> >
> >    /* Create a hash_map in ggc memory.  */
> > -  static hash_map *create_ggc (size_t size,
> > +  static hash_map *create_ggc (size_t size = default_size,
> >                                bool gather_mem_stats = GATHER_STATISTICS
> >                                CXX_MEM_STAT_INFO)
> >      {
> > @@ -326,4 +327,37 @@ gt_pch_nx (hash_map<K, V, H> *h, gt_pointer_operator op, void *cookie)
> >    op (&h->m_table.m_entries, cookie);
> >  }
> >
> > +template<typename K, typename V, typename H>
> > +inline hash_map<K,V,H> *
> > +hash_map_maybe_create (hash_map<K,V,H> *&h)
> > +{
> > +  if (!h)
> > +    h = h->create_ggc ();
> > +  return h;
> > +}
> > +
> > +/* Like h->get, but handles null h.  */
> > +template<typename K, typename V, typename H>
> > +inline V*
> > +hash_map_safe_get (hash_map<K,V,H> *h, const K& k)
> > +{
> > +  return h ? h->get (k) : NULL;
> > +}
> > +
> > +/* Like h->get, but handles null h.  */
> > +template<typename K, typename V, typename H>
> > +inline V&
> > +hash_map_safe_get_or_insert (hash_map<K,V,H> *&h, const K& k, bool *e = NULL)
> > +{
> > +  return hash_map_maybe_create (h)->get_or_insert (k, e);
> > +}
> > +
> > +/* Like h->put, but handles null h.  */
> > +template<typename K, typename V, typename H>
> > +inline bool
> > +hash_map_safe_put (hash_map<K,V,H> *&h, const K& k, const V& v)
> > +{
> > +  return hash_map_maybe_create (h)->put (k, v);
> > +}
> > +
> >  #endif
> > diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
> > index cb5484f4b72..904b70a9c99 100644
> > --- a/gcc/cp/constexpr.c
> > +++ b/gcc/cp/constexpr.c
> > @@ -1098,15 +1098,6 @@ maybe_initialize_constexpr_call_table (void)
> >
> >  static GTY(()) hash_map<tree, tree> *fundef_copies_table;
> >
> > -/* Initialize FUNDEF_COPIES_TABLE if it's not initialized.  */
> > -
> > -static void
> > -maybe_initialize_fundef_copies_table ()
> > -{
> > -  if (fundef_copies_table == NULL)
> > -    fundef_copies_table = hash_map<tree,tree>::create_ggc (101);
> > -}
> > -
> >  /* Reuse a copy or create a new unshared copy of the function FUN.
> >     Return this copy.  We use a TREE_LIST whose PURPOSE is body, VALUE
> >     is parms, TYPE is result.  */
> > @@ -1114,11 +1105,10 @@ maybe_initialize_fundef_copies_table ()
> >  static tree
> >  get_fundef_copy (constexpr_fundef *fundef)
> >  {
> > -  maybe_initialize_fundef_copies_table ();
> > -
> >    tree copy;
> >    bool existed;
> > -  tree *slot = &fundef_copies_table->get_or_insert (fundef->decl, &existed);
> > +  tree *slot = &hash_map_safe_get_or_insert (fundef_copies_table,
> > +                                            fundef->decl, &existed);
> >
> >    if (!existed)
> >      {
> > diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c
> > index 4369a5b5570..652b94230ad 100644
> > --- a/gcc/cp/cp-objcp-common.c
> > +++ b/gcc/cp/cp-objcp-common.c
> > @@ -145,11 +145,9 @@ cp_get_debug_type (const_tree type)
> >    if (dtype)
> >      {
> >        tree ktype = CONST_CAST_TREE (type);
> > -      if (debug_type_map == NULL)
> > -       debug_type_map = tree_cache_map::create_ggc (512);
> > -      else if (tree *slot = debug_type_map->get (ktype))
> > +      if (tree *slot = hash_map_safe_get (debug_type_map, ktype))
> >         return *slot;
> > -      debug_type_map->put (ktype, dtype);
> > +      hash_map_safe_put (debug_type_map, ktype, dtype);
> >      }
> >
> >    return dtype;
> > diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
> > index 67c4521e98c..562fe10bd96 100644
> > --- a/gcc/cp/decl.c
> > +++ b/gcc/cp/decl.c
> > @@ -7704,13 +7704,6 @@ get_tuple_decomp_init (tree decl, unsigned i)
> >     based on the actual type of the variable, so store it in a hash table.  */
> >
> >  static GTY((cache)) tree_cache_map *decomp_type_table;
> > -static void
> > -store_decomp_type (tree v, tree t)
> > -{
> > -  if (!decomp_type_table)
> > -    decomp_type_table = tree_cache_map::create_ggc (13);
> > -  decomp_type_table->put (v, t);
> > -}
> >
> >  tree
> >  lookup_decomp_type (tree v)
> > @@ -7946,7 +7939,7 @@ cp_finish_decomp (tree decl, tree first, unsigned int count)
> >               goto error_out;
> >             }
> >           /* Save the decltype away before reference collapse.  */
> > -         store_decomp_type (v[i], eltype);
> > +         hash_map_safe_put (decomp_type_table, v[i], eltype);
> >           eltype = cp_build_reference_type (eltype, !lvalue_p (init));
> >           TREE_TYPE (v[i]) = eltype;
> >           layout_decl (v[i], 0);
> > diff --git a/gcc/cp/init.c b/gcc/cp/init.c
> > index 67e06568b2f..4bd60859bf8 100644
> > --- a/gcc/cp/init.c
> > +++ b/gcc/cp/init.c
> > @@ -563,10 +563,9 @@ get_nsdmi (tree member, bool in_ctor, tsubst_flags_t complain)
> >        init = DECL_INITIAL (DECL_TI_TEMPLATE (member));
> >        location_t expr_loc
> >         = cp_expr_loc_or_loc (init, DECL_SOURCE_LOCATION (member));
> > -      tree *slot;
> >        if (TREE_CODE (init) == DEFERRED_PARSE)
> >         /* Unparsed.  */;
> > -      else if (nsdmi_inst && (slot = nsdmi_inst->get (member)))
> > +      else if (tree *slot = hash_map_safe_get (nsdmi_inst, member))
> >         init = *slot;
> >        /* Check recursive instantiation.  */
> >        else if (DECL_INSTANTIATING_NSDMI_P (member))
> > @@ -611,11 +610,7 @@ get_nsdmi (tree member, bool in_ctor, tsubst_flags_t complain)
> >           DECL_INSTANTIATING_NSDMI_P (member) = 0;
> >
> >           if (init != error_mark_node)
> > -           {
> > -             if (!nsdmi_inst)
> > -               nsdmi_inst = tree_cache_map::create_ggc (37);
> > -             nsdmi_inst->put (member, init);
> > -           }
> > +           hash_map_safe_put (nsdmi_inst, member, init);
> >
> >           if (pushed)
> >             {
> > diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
> > index 44b36183304..d2aeb1ccba6 100644
> > --- a/gcc/cp/pt.c
> > +++ b/gcc/cp/pt.c
> > @@ -7357,21 +7357,6 @@ coerce_template_args_for_ttp (tree templ, tree arglist,
> >  /* A cache of template template parameters with match-all default
> >     arguments.  */
> >  static GTY((deletable)) hash_map<tree,tree> *defaulted_ttp_cache;
> > -static void
> > -store_defaulted_ttp (tree v, tree t)
> > -{
> > -  if (!defaulted_ttp_cache)
> > -    defaulted_ttp_cache = hash_map<tree,tree>::create_ggc (13);
> > -  defaulted_ttp_cache->put (v, t);
> > -}
> > -static tree
> > -lookup_defaulted_ttp (tree v)
> > -{
> > -  if (defaulted_ttp_cache)
> > -    if (tree *p = defaulted_ttp_cache->get (v))
> > -      return *p;
> > -  return NULL_TREE;
> > -}
> >
> >  /* T is a bound template template-parameter.  Copy its arguments into default
> >     arguments of the template template-parameter's template parameters.  */
> > @@ -7379,8 +7364,8 @@ lookup_defaulted_ttp (tree v)
> >  static tree
> >  add_defaults_to_ttp (tree otmpl)
> >  {
> > -  if (tree c = lookup_defaulted_ttp (otmpl))
> > -    return c;
> > +  if (tree *c = hash_map_safe_get (defaulted_ttp_cache, otmpl))
> > +    return *c;
> >
> >    tree ntmpl = copy_node (otmpl);
> >
> > @@ -7410,7 +7395,7 @@ add_defaults_to_ttp (tree otmpl)
> >         }
> >      }
> >
> > -  store_defaulted_ttp (otmpl, ntmpl);
> > +  hash_map_safe_put (defaulted_ttp_cache, otmpl, ntmpl);
> >    return ntmpl;
> >  }
> >
> > diff --git a/gcc/hash-table.c b/gcc/hash-table.c
> > index e3b5d3da09e..3520c3bb596 100644
> > --- a/gcc/hash-table.c
> > +++ b/gcc/hash-table.c
> > @@ -78,7 +78,7 @@ struct prime_ent const prime_tab[] = {
> >  unsigned int hash_table_sanitize_eq_limit;
> >
> >  /* The following function returns an index into the above table of the
> > -   nearest prime number which is greater than N, and near a power of two. */
> > +   nearest prime number which is at least N, and near a power of two. */
> >
> >  unsigned int
> >  hash_table_higher_prime_index (unsigned long n)
> >
> > base-commit: c6fd1c4cf03b10c7ab34dea84f70c618c824599e
> > --
> > 2.21.0
> >
>
Jason Merrill Oct. 1, 2019, 6:50 p.m. UTC | #3
On 10/1/19 3:34 AM, Richard Biener wrote:
> On Mon, Sep 30, 2019 at 8:33 PM Jason Merrill <jason@redhat.com> wrote:
>>
>> My comments accidentally got lost.
>>
>> Several places in the front-end (and elsewhere) use the same lazy
>> allocation pattern for hash_maps, and this patch replaces them with
>> hash_map_safe_* functions like vec_safe_*.  They don't provide a way
>> to specify an initial size, but I don't think that's a significant
>> issue.
>>
>> Tested x86_64-pc-linux-gnu.  OK for trunk?
> 
> You are using create_ggc but the new functions do not indicate that ggc
> allocation is done.
> It's then also incomplete with not having a non-ggc variant
> of them?  Maybe I'm missing something.

Ah, I had been thinking that this lazy pattern would only be used with 
ggc, but I see that I was wrong.  How's this?

Incidentally, now I see another C++11 feature I'd like to be able to 
use: default template arguments for function templates.
Richard Biener Oct. 2, 2019, 8:28 a.m. UTC | #4
On Tue, Oct 1, 2019 at 8:50 PM Jason Merrill <jason@redhat.com> wrote:
>
> On 10/1/19 3:34 AM, Richard Biener wrote:
> > On Mon, Sep 30, 2019 at 8:33 PM Jason Merrill <jason@redhat.com> wrote:
> >>
> >> My comments accidentally got lost.
> >>
> >> Several places in the front-end (and elsewhere) use the same lazy
> >> allocation pattern for hash_maps, and this patch replaces them with
> >> hash_map_safe_* functions like vec_safe_*.  They don't provide a way
> >> to specify an initial size, but I don't think that's a significant
> >> issue.
> >>
> >> Tested x86_64-pc-linux-gnu.  OK for trunk?
> >
> > You are using create_ggc but the new functions do not indicate that ggc
> > allocation is done.
> > It's then also incomplete with not having a non-ggc variant
> > of them?  Maybe I'm missing something.
>
> Ah, I had been thinking that this lazy pattern would only be used with
> ggc, but I see that I was wrong.  How's this?
>
> Incidentally, now I see another C++11 feature I'd like to be able to
> use: default template arguments for function templates.

I presume

template<bool ggc, typename K, typename V, typename H>
inline bool
hash_map_safe_put (hash_map<K,V,H> *&h, const K& k, const V& v, size_t
size = default_hash_map_size)
{
  return hash_map_maybe_create<ggc> (h, size)->put (k, v);
}

was deemed to ugly?  IMHO instantiating the templates for different sizes
is unwanted compile-time overhead (plus not being able to use
a default value makes non-default values creep into the code-base?).

I'd have OKed a variant like above, so - would that work for you
(change hash_map_maybe_create as well then, of course).

Thanks,
Richard.
Jason Merrill Oct. 2, 2019, 7:26 p.m. UTC | #5
On 10/2/19 4:28 AM, Richard Biener wrote:
> On Tue, Oct 1, 2019 at 8:50 PM Jason Merrill <jason@redhat.com> wrote:
>>
>> On 10/1/19 3:34 AM, Richard Biener wrote:
>>> On Mon, Sep 30, 2019 at 8:33 PM Jason Merrill <jason@redhat.com> wrote:
>>>>
>>>> My comments accidentally got lost.
>>>>
>>>> Several places in the front-end (and elsewhere) use the same lazy
>>>> allocation pattern for hash_maps, and this patch replaces them with
>>>> hash_map_safe_* functions like vec_safe_*.  They don't provide a way
>>>> to specify an initial size, but I don't think that's a significant
>>>> issue.
>>>>
>>>> Tested x86_64-pc-linux-gnu.  OK for trunk?
>>>
>>> You are using create_ggc but the new functions do not indicate that ggc
>>> allocation is done.
>>> It's then also incomplete with not having a non-ggc variant
>>> of them?  Maybe I'm missing something.
>>
>> Ah, I had been thinking that this lazy pattern would only be used with
>> ggc, but I see that I was wrong.  How's this?
>>
>> Incidentally, now I see another C++11 feature I'd like to be able to
>> use: default template arguments for function templates.
> 
> I presume
> 
> template<bool ggc, typename K, typename V, typename H>
> inline bool
> hash_map_safe_put (hash_map<K,V,H> *&h, const K& k, const V& v, size_t
> size = default_hash_map_size)
> {
>    return hash_map_maybe_create<ggc> (h, size)->put (k, v);
> }
> 
> was deemed to ugly?  IMHO instantiating the templates for different sizes
> is unwanted compile-time overhead (plus not being able to use
> a default value makes non-default values creep into the code-base?).
> 
> I'd have OKed a variant like above, so - would that work for you
> (change hash_map_maybe_create as well then, of course).

Sure.  Applying this version:
diff mbox series

Patch

diff --git a/gcc/hash-map.h b/gcc/hash-map.h
index ba20fe79f23..e638f761465 100644
--- a/gcc/hash-map.h
+++ b/gcc/hash-map.h
@@ -128,8 +128,9 @@  class GTY((user)) hash_map
 	}
   };
 
+  static const size_t default_size = 13;
 public:
-  explicit hash_map (size_t n = 13, bool ggc = false,
+  explicit hash_map (size_t n = default_size, bool ggc = false,
 		     bool sanitize_eq_and_hash = true,
 		     bool gather_mem_stats = GATHER_STATISTICS
 		     CXX_MEM_STAT_INFO)
@@ -146,7 +147,7 @@  public:
 	       HASH_MAP_ORIGIN PASS_MEM_STAT) {}
 
   /* Create a hash_map in ggc memory.  */
-  static hash_map *create_ggc (size_t size,
+  static hash_map *create_ggc (size_t size = default_size,
 			       bool gather_mem_stats = GATHER_STATISTICS
 			       CXX_MEM_STAT_INFO)
     {
@@ -326,4 +327,37 @@  gt_pch_nx (hash_map<K, V, H> *h, gt_pointer_operator op, void *cookie)
   op (&h->m_table.m_entries, cookie);
 }
 
+template<typename K, typename V, typename H>
+inline hash_map<K,V,H> *
+hash_map_maybe_create (hash_map<K,V,H> *&h)
+{
+  if (!h)
+    h = h->create_ggc ();
+  return h;
+}
+
+/* Like h->get, but handles null h.  */
+template<typename K, typename V, typename H>
+inline V*
+hash_map_safe_get (hash_map<K,V,H> *h, const K& k)
+{
+  return h ? h->get (k) : NULL;
+}
+
+/* Like h->get, but handles null h.  */
+template<typename K, typename V, typename H>
+inline V&
+hash_map_safe_get_or_insert (hash_map<K,V,H> *&h, const K& k, bool *e = NULL)
+{
+  return hash_map_maybe_create (h)->get_or_insert (k, e);
+}
+
+/* Like h->put, but handles null h.  */
+template<typename K, typename V, typename H>
+inline bool
+hash_map_safe_put (hash_map<K,V,H> *&h, const K& k, const V& v)
+{
+  return hash_map_maybe_create (h)->put (k, v);
+}
+
 #endif
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index cb5484f4b72..904b70a9c99 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -1098,15 +1098,6 @@  maybe_initialize_constexpr_call_table (void)
 
 static GTY(()) hash_map<tree, tree> *fundef_copies_table;
 
-/* Initialize FUNDEF_COPIES_TABLE if it's not initialized.  */
-
-static void
-maybe_initialize_fundef_copies_table ()
-{
-  if (fundef_copies_table == NULL)
-    fundef_copies_table = hash_map<tree,tree>::create_ggc (101);
-}
-
 /* Reuse a copy or create a new unshared copy of the function FUN.
    Return this copy.  We use a TREE_LIST whose PURPOSE is body, VALUE
    is parms, TYPE is result.  */
@@ -1114,11 +1105,10 @@  maybe_initialize_fundef_copies_table ()
 static tree
 get_fundef_copy (constexpr_fundef *fundef)
 {
-  maybe_initialize_fundef_copies_table ();
-
   tree copy;
   bool existed;
-  tree *slot = &fundef_copies_table->get_or_insert (fundef->decl, &existed);
+  tree *slot = &hash_map_safe_get_or_insert (fundef_copies_table,
+					     fundef->decl, &existed);
 
   if (!existed)
     {
diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c
index 4369a5b5570..652b94230ad 100644
--- a/gcc/cp/cp-objcp-common.c
+++ b/gcc/cp/cp-objcp-common.c
@@ -145,11 +145,9 @@  cp_get_debug_type (const_tree type)
   if (dtype)
     {
       tree ktype = CONST_CAST_TREE (type);
-      if (debug_type_map == NULL)
-	debug_type_map = tree_cache_map::create_ggc (512);
-      else if (tree *slot = debug_type_map->get (ktype))
+      if (tree *slot = hash_map_safe_get (debug_type_map, ktype))
 	return *slot;
-      debug_type_map->put (ktype, dtype);
+      hash_map_safe_put (debug_type_map, ktype, dtype);
     }
 
   return dtype;
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 67c4521e98c..562fe10bd96 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -7704,13 +7704,6 @@  get_tuple_decomp_init (tree decl, unsigned i)
    based on the actual type of the variable, so store it in a hash table.  */
 
 static GTY((cache)) tree_cache_map *decomp_type_table;
-static void
-store_decomp_type (tree v, tree t)
-{
-  if (!decomp_type_table)
-    decomp_type_table = tree_cache_map::create_ggc (13);
-  decomp_type_table->put (v, t);
-}
 
 tree
 lookup_decomp_type (tree v)
@@ -7946,7 +7939,7 @@  cp_finish_decomp (tree decl, tree first, unsigned int count)
 	      goto error_out;
 	    }
 	  /* Save the decltype away before reference collapse.  */
-	  store_decomp_type (v[i], eltype);
+	  hash_map_safe_put (decomp_type_table, v[i], eltype);
 	  eltype = cp_build_reference_type (eltype, !lvalue_p (init));
 	  TREE_TYPE (v[i]) = eltype;
 	  layout_decl (v[i], 0);
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 67e06568b2f..4bd60859bf8 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -563,10 +563,9 @@  get_nsdmi (tree member, bool in_ctor, tsubst_flags_t complain)
       init = DECL_INITIAL (DECL_TI_TEMPLATE (member));
       location_t expr_loc
 	= cp_expr_loc_or_loc (init, DECL_SOURCE_LOCATION (member));
-      tree *slot;
       if (TREE_CODE (init) == DEFERRED_PARSE)
 	/* Unparsed.  */;
-      else if (nsdmi_inst && (slot = nsdmi_inst->get (member)))
+      else if (tree *slot = hash_map_safe_get (nsdmi_inst, member))
 	init = *slot;
       /* Check recursive instantiation.  */
       else if (DECL_INSTANTIATING_NSDMI_P (member))
@@ -611,11 +610,7 @@  get_nsdmi (tree member, bool in_ctor, tsubst_flags_t complain)
 	  DECL_INSTANTIATING_NSDMI_P (member) = 0;
 
 	  if (init != error_mark_node)
-	    {
-	      if (!nsdmi_inst)
-		nsdmi_inst = tree_cache_map::create_ggc (37);
-	      nsdmi_inst->put (member, init);
-	    }
+	    hash_map_safe_put (nsdmi_inst, member, init);
 
 	  if (pushed)
 	    {
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 44b36183304..d2aeb1ccba6 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -7357,21 +7357,6 @@  coerce_template_args_for_ttp (tree templ, tree arglist,
 /* A cache of template template parameters with match-all default
    arguments.  */
 static GTY((deletable)) hash_map<tree,tree> *defaulted_ttp_cache;
-static void
-store_defaulted_ttp (tree v, tree t)
-{
-  if (!defaulted_ttp_cache)
-    defaulted_ttp_cache = hash_map<tree,tree>::create_ggc (13);
-  defaulted_ttp_cache->put (v, t);
-}
-static tree
-lookup_defaulted_ttp (tree v)
-{
-  if (defaulted_ttp_cache)
-    if (tree *p = defaulted_ttp_cache->get (v))
-      return *p;
-  return NULL_TREE;
-}
 
 /* T is a bound template template-parameter.  Copy its arguments into default
    arguments of the template template-parameter's template parameters.  */
@@ -7379,8 +7364,8 @@  lookup_defaulted_ttp (tree v)
 static tree
 add_defaults_to_ttp (tree otmpl)
 {
-  if (tree c = lookup_defaulted_ttp (otmpl))
-    return c;
+  if (tree *c = hash_map_safe_get (defaulted_ttp_cache, otmpl))
+    return *c;
 
   tree ntmpl = copy_node (otmpl);
 
@@ -7410,7 +7395,7 @@  add_defaults_to_ttp (tree otmpl)
 	}
     }
 
-  store_defaulted_ttp (otmpl, ntmpl);
+  hash_map_safe_put (defaulted_ttp_cache, otmpl, ntmpl);
   return ntmpl;
 }
 
diff --git a/gcc/hash-table.c b/gcc/hash-table.c
index e3b5d3da09e..3520c3bb596 100644
--- a/gcc/hash-table.c
+++ b/gcc/hash-table.c
@@ -78,7 +78,7 @@  struct prime_ent const prime_tab[] = {
 unsigned int hash_table_sanitize_eq_limit;
 
 /* The following function returns an index into the above table of the
-   nearest prime number which is greater than N, and near a power of two. */
+   nearest prime number which is at least N, and near a power of two. */
 
 unsigned int
 hash_table_higher_prime_index (unsigned long n)