[PATCH] support ggc hash_map and hash_set

Richard Biener richard.guenther@gmail.com
Wed Oct 15 07:34:00 GMT 2014


On Wed, Oct 15, 2014 at 4:57 AM, Trevor Saunders <tsaunders@mozilla.com> wrote:
> On Tue, Oct 14, 2014 at 04:05:25PM +0200, Richard Biener wrote:
>> On Tue, Sep 2, 2014 at 3:56 AM,  <tsaunders@mozilla.com> wrote:
>> > From: Trevor Saunders <tsaunders@mozilla.com>
>> >
>> > Hi,
>> >
>> > There are still some issues to make this work really nicely, but this part is
>> > probably good enough its worth reviewing.
>> >
>> > For one thing you can't use ggc hash_map or set in front ends with some types
>> > or gengtype will decide to put the overloads of the marking routines it
>> > provides in a front end file instead of the one it choose before breaking other
>> > front ends.  However that seems to be an unrelated issue you can trigger it
>> > without using hash_map/set, so we might as well solve it separetly.
>> >
>> > I had to have the entry marking functions for set deligate to the traits class
>> > because gcc < 4.9.1 issues clearly bogus errors if you inline the code from the
>> > traits implementation.  We may well want to make map work the same way at some
>> > point to enable some of the special GTY attributes like if_marked, but it
>> > doesn't seem to be necessary right now.
>> >
>> > bootstrapped + regtested without regressions on x86_64-unknown-linux-gnu, ok?
>>
>> I have just noticed that this (ggc support for hash-table.h) makes it no longer
>> suitable for use from generator programs (trying to merge from trunk on
>> match-and-simplify).  If you look at vec.h it has sophisticated guards
>> to block out GGC support if GENERATOR_FILE is defined.
>
> yeah, it works, but its kind of messy since some of the generator
> programs include ggc.h.
>
>> Can you try to fix this please?
>
> I expect its doable, I can try to get it done later this week / week
> end, but next few days are busy for me.

Something as simple as the following works for me on the branch
(but maybe too hackish to declare but not define the ggc alloc templates).

Richard.

> Trev
>
>>
>> Thanks,
>> Richard.
>>
>> > Trev
>> >
>> > gcc/ChangeLog:
>> >
>> > 2014-09-01  Trevor Saunders  <tsaunders@mozilla.com>
>> >
>> >         * alloc-pool.c: Include coretypes.h.
>> >         * cgraph.h, dbxout.c, dwarf2out.c, except.c, except.h, function.c,
>> >         function.h, symtab.c, tree-cfg.c, tree-eh.c: Use hash_map and
>> >         hash_set instead of htab.
>> >         * ggc-page.c (in_gc): New variable.
>> >         (ggc_free): Do nothing if a collection is taking place.
>> >         (ggc_collect): Set in_gc appropriately.
>> >         * ggc.h (gt_ggc_mx(const char *)): New function.
>> >         (gt_pch_nx(const char *)): Likewise.
>> >         (gt_ggc_mx(int)): Likewise.
>> >         (gt_pch_nx(int)): Likewise.
>> >         * hash-map.h (hash_map::hash_entry::ggc_mx): Likewise.
>> >         (hash_map::hash_entry::pch_nx): Likewise.
>> >         (hash_map::hash_entry::pch_nx_helper): Likewise.
>> > (hash_map::hash_map): Adjust.
>> > (hash_map::create_ggc): New function.
>> > (gt_ggc_mx): Likewise.
>> > (gt_pch_nx): Likewise.
>> >         * hash-set.h (default_hashset_traits::ggc_mx): Likewise.
>> > (default_hashset_traits::pch_nx): Likewise.
>> > (hash_set::hash_entry::ggc_mx): Likewise.
>> > (hash_set::hash_entry::pch_nx): Likewise.
>> > (hash_set::hash_entry::pch_nx_helper): Likewise.
>> > (hash_set::hash_set): Adjust.
>> > (hash_set::create_ggc): New function.
>> > (hash_set::elements): Likewise.
>> > (gt_ggc_mx): Likewise.
>> > (gt_pch_nx): Likewise.
>> >         * hash-table.h (hash_table::hash_table): Adjust.
>> > (hash_table::m_ggc): New member.
>> >         (hash_table::~hash_table): Adjust.
>> >         (hash_table::expand): Likewise.
>> >         (hash_table::empty): Likewise.
>> > (gt_ggc_mx): New function.
>> >         (hashtab_entry_note_pointers): Likewise.
>> > (gt_pch_nx): Likewise.
>> >
>> >
>> > diff --git a/gcc/alloc-pool.c b/gcc/alloc-pool.c
>> > index 0d31835..bfaa0e4 100644
>> > --- a/gcc/alloc-pool.c
>> > +++ b/gcc/alloc-pool.c
>> > @@ -20,6 +20,7 @@ along with GCC; see the file COPYING3.  If not see
>> >
>> >  #include "config.h"
>> >  #include "system.h"
>> > +#include "coretypes.h"
>> >  #include "alloc-pool.h"
>> >  #include "hash-table.h"
>> >  #include "hash-map.h"
>> > diff --git a/gcc/cgraph.h b/gcc/cgraph.h
>> > index 879899c..030a1c7 100644
>> > --- a/gcc/cgraph.h
>> > +++ b/gcc/cgraph.h
>> > @@ -1604,7 +1604,6 @@ struct cgraph_2node_hook_list;
>> >
>> >  /* Map from a symbol to initialization/finalization priorities.  */
>> >  struct GTY(()) symbol_priority_map {
>> > -  symtab_node *symbol;
>> >    priority_type init;
>> >    priority_type fini;
>> >  };
>> > @@ -1872,7 +1871,7 @@ public:
>> >    htab_t GTY((param_is (symtab_node))) assembler_name_hash;
>> >
>> >    /* Hash table used to hold init priorities.  */
>> > -  htab_t GTY ((param_is (symbol_priority_map))) init_priority_hash;
>> > +  hash_map<symtab_node *, symbol_priority_map> *init_priority_hash;
>> >
>> >    FILE* GTY ((skip)) dump_file;
>> >
>> > diff --git a/gcc/dbxout.c b/gcc/dbxout.c
>> > index 946f1d1..d856bdd 100644
>> > --- a/gcc/dbxout.c
>> > +++ b/gcc/dbxout.c
>> > @@ -2484,12 +2484,9 @@ dbxout_expand_expr (tree expr)
>> >  /* Helper function for output_used_types.  Queue one entry from the
>> >     used types hash to be output.  */
>> >
>> > -static int
>> > -output_used_types_helper (void **slot, void *data)
>> > +bool
>> > +output_used_types_helper (tree const &type, vec<tree> *types_p)
>> >  {
>> > -  tree type = (tree) *slot;
>> > -  vec<tree> *types_p = (vec<tree> *) data;
>> > -
>> >    if ((TREE_CODE (type) == RECORD_TYPE
>> >         || TREE_CODE (type) == UNION_TYPE
>> >         || TREE_CODE (type) == QUAL_UNION_TYPE
>> > @@ -2502,7 +2499,7 @@ output_used_types_helper (void **slot, void *data)
>> >            && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL)
>> >      types_p->quick_push (TYPE_NAME (type));
>> >
>> > -  return 1;
>> > +  return true;
>> >  }
>> >
>> >  /* This is a qsort callback which sorts types and declarations into a
>> > @@ -2544,8 +2541,9 @@ output_used_types (void)
>> >        int i;
>> >        tree type;
>> >
>> > -      types.create (htab_elements (cfun->used_types_hash));
>> > -      htab_traverse (cfun->used_types_hash, output_used_types_helper, &types);
>> > +      types.create (cfun->used_types_hash->elements ());
>> > +      cfun->used_types_hash->traverse<vec<tree> *, output_used_types_helper>
>> > +               (&types);
>> >
>> >        /* Sort by UID to prevent dependence on hash table ordering.  */
>> >        types.qsort (output_types_sort);
>> > diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
>> > index 7c0be86..21afc3f 100644
>> > --- a/gcc/dwarf2out.c
>> > +++ b/gcc/dwarf2out.c
>> > @@ -18013,17 +18013,15 @@ dwarf2out_abstract_function (tree decl)
>> >     Marks the DIE of a given type in *SLOT as perennial, so it never gets
>> >     marked as unused by prune_unused_types.  */
>> >
>> > -static int
>> > -premark_used_types_helper (void **slot, void *data ATTRIBUTE_UNUSED)
>> > +bool
>> > +premark_used_types_helper (tree const &type, void *)
>> >  {
>> > -  tree type;
>> >    dw_die_ref die;
>> >
>> > -  type = (tree) *slot;
>> >    die = lookup_type_die (type);
>> >    if (die != NULL)
>> >      die->die_perennial_p = 1;
>> > -  return 1;
>> > +  return true;
>> >  }
>> >
>> >  /* Helper function of premark_types_used_by_global_vars which gets called
>> > @@ -18066,7 +18064,7 @@ static void
>> >  premark_used_types (struct function *fun)
>> >  {
>> >    if (fun && fun->used_types_hash)
>> > -    htab_traverse (fun->used_types_hash, premark_used_types_helper, NULL);
>> > +    fun->used_types_hash->traverse<void *, premark_used_types_helper> (NULL);
>> >  }
>> >
>> >  /* Mark all members of types_used_by_vars_entry as perennial.  */
>> > diff --git a/gcc/except.c b/gcc/except.c
>> > index 1f57c3f..fecc060 100644
>> > --- a/gcc/except.c
>> > +++ b/gcc/except.c
>> > @@ -149,8 +149,13 @@ along with GCC; see the file COPYING3.  If not see
>> >  #endif
>> >
>> >  static GTY(()) int call_site_base;
>> > -static GTY ((param_is (union tree_node)))
>> > -  htab_t type_to_runtime_map;
>> > +
>> > +struct tree_hash_traits : default_hashmap_traits
>> > +{
>> > +  static hashval_t hash (tree t) { return TREE_HASH (t); }
>> > +};
>> > +
>> > +static GTY (()) hash_map<tree, tree, tree_hash_traits> *type_to_runtime_map;
>> >
>> >  /* Describe the SjLj_Function_Context structure.  */
>> >  static GTY(()) tree sjlj_fc_type_node;
>> > @@ -213,9 +218,6 @@ typedef hash_table<action_record_hasher> action_hash_type;
>> >  static bool get_eh_region_and_lp_from_rtx (const_rtx, eh_region *,
>> >                                            eh_landing_pad *);
>> >
>> > -static int t2r_eq (const void *, const void *);
>> > -static hashval_t t2r_hash (const void *);
>> > -
>> >  static void dw2_build_landing_pads (void);
>> >
>> >  static int collect_one_action_chain (action_hash_type *, eh_region);
>> > @@ -237,7 +239,8 @@ init_eh (void)
>> >    if (! flag_exceptions)
>> >      return;
>> >
>> > -  type_to_runtime_map = htab_create_ggc (31, t2r_hash, t2r_eq, NULL);
>> > +  type_to_runtime_map
>> > +    = hash_map<tree, tree, tree_hash_traits>::create_ggc (31);
>> >
>> >    /* Create the SjLj_Function_Context structure.  This should match
>> >       the definition in unwind-sjlj.c.  */
>> > @@ -671,54 +674,28 @@ eh_region_outermost (struct function *ifun, eh_region region_a,
>> >    return region_a;
>> >  }
>> >
>> > -static int
>> > -t2r_eq (const void *pentry, const void *pdata)
>> > -{
>> > -  const_tree const entry = (const_tree) pentry;
>> > -  const_tree const data = (const_tree) pdata;
>> > -
>> > -  return TREE_PURPOSE (entry) == data;
>> > -}
>> > -
>> > -static hashval_t
>> > -t2r_hash (const void *pentry)
>> > -{
>> > -  const_tree const entry = (const_tree) pentry;
>> > -  return TREE_HASH (TREE_PURPOSE (entry));
>> > -}
>> > -
>> >  void
>> >  add_type_for_runtime (tree type)
>> >  {
>> > -  tree *slot;
>> > -
>> >    /* If TYPE is NOP_EXPR, it means that it already is a runtime type.  */
>> >    if (TREE_CODE (type) == NOP_EXPR)
>> >      return;
>> >
>> > -  slot = (tree *) htab_find_slot_with_hash (type_to_runtime_map, type,
>> > -                                           TREE_HASH (type), INSERT);
>> > -  if (*slot == NULL)
>> > -    {
>> > -      tree runtime = lang_hooks.eh_runtime_type (type);
>> > -      *slot = tree_cons (type, runtime, NULL_TREE);
>> > -    }
>> > +  bool existed = false;
>> > +  tree *slot = &type_to_runtime_map->get_or_insert (type, &existed);
>> > +  if (!existed)
>> > +    *slot = lang_hooks.eh_runtime_type (type);
>> >  }
>> >
>> >  tree
>> >  lookup_type_for_runtime (tree type)
>> >  {
>> > -  tree *slot;
>> > -
>> >    /* If TYPE is NOP_EXPR, it means that it already is a runtime type.  */
>> >    if (TREE_CODE (type) == NOP_EXPR)
>> >      return type;
>> >
>> > -  slot = (tree *) htab_find_slot_with_hash (type_to_runtime_map, type,
>> > -                                           TREE_HASH (type), NO_INSERT);
>> > -
>> >    /* We should have always inserted the data earlier.  */
>> > -  return TREE_VALUE (*slot);
>> > +  return *type_to_runtime_map->get (type);
>> >  }
>> >
>> >
>> > @@ -3150,12 +3127,12 @@ output_function_exception_table (const char *fnname)
>> >  }
>> >
>> >  void
>> > -set_eh_throw_stmt_table (struct function *fun, struct htab *table)
>> > +set_eh_throw_stmt_table (function *fun, hash_map<gimple, int> *table)
>> >  {
>> >    fun->eh->throw_stmt_table = table;
>> >  }
>> >
>> > -htab_t
>> > +hash_map<gimple, int> *
>> >  get_eh_throw_stmt_table (struct function *fun)
>> >  {
>> >    return fun->eh->throw_stmt_table;
>> > diff --git a/gcc/except.h b/gcc/except.h
>> > index 71a8dce..3259151 100644
>> > --- a/gcc/except.h
>> > +++ b/gcc/except.h
>> > @@ -204,7 +204,7 @@ struct GTY(()) eh_status
>> >
>> >    /* At the gimple level, a mapping from gimple statement to landing pad
>> >       or must-not-throw region.  See record_stmt_eh_region.  */
>> > -  htab_t GTY((param_is (struct throw_stmt_node))) throw_stmt_table;
>> > +  hash_map<gimple, int> *GTY(()) throw_stmt_table;
>> >
>> >    /* All of the runtime type data used by the function.  These objects
>> >       are emitted to the lang-specific-data-area for the function.  */
>> > @@ -291,8 +291,8 @@ struct GTY(()) throw_stmt_node {
>> >    int lp_nr;
>> >  };
>> >
>> > -extern struct htab *get_eh_throw_stmt_table (struct function *);
>> > -extern void set_eh_throw_stmt_table (struct function *, struct htab *);
>> > +extern hash_map<gimple, int> *get_eh_throw_stmt_table (struct function *);
>> > +extern void set_eh_throw_stmt_table (function *, hash_map<gimple, int> *);
>> >
>> >  enum eh_personality_kind {
>> >    eh_personality_none,
>> > diff --git a/gcc/function.c b/gcc/function.c
>> > index 464c6cd..2e46799 100644
>> > --- a/gcc/function.c
>> > +++ b/gcc/function.c
>> > @@ -6093,14 +6093,10 @@ used_types_insert_helper (tree type, struct function *func)
>> >  {
>> >    if (type != NULL && func != NULL)
>> >      {
>> > -      void **slot;
>> > -
>> >        if (func->used_types_hash == NULL)
>> > -       func->used_types_hash = htab_create_ggc (37, htab_hash_pointer,
>> > -                                                htab_eq_pointer, NULL);
>> > -      slot = htab_find_slot (func->used_types_hash, type, INSERT);
>> > -      if (*slot == NULL)
>> > -       *slot = type;
>> > +       func->used_types_hash = hash_set<tree>::create_ggc (37);
>> > +
>> > +      func->used_types_hash->add (type);
>> >      }
>> >  }
>> >
>> > diff --git a/gcc/function.h b/gcc/function.h
>> > index 071f5dd..e71210d 100644
>> > --- a/gcc/function.h
>> > +++ b/gcc/function.h
>> > @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3.  If not see
>> >  #define GCC_FUNCTION_H
>> >
>> >  #include "hashtab.h"
>> > +#include "hash-set.h"
>> >  #include "vec.h"
>> >  #include "machmode.h"
>> >  #include "tm.h"                        /* For CUMULATIVE_ARGS.  */
>> > @@ -564,7 +565,7 @@ struct GTY(()) function {
>> >    struct language_function * language;
>> >
>> >    /* Used types hash table.  */
>> > -  htab_t GTY ((param_is (union tree_node))) used_types_hash;
>> > +  hash_set<tree> *GTY (()) used_types_hash;
>> >
>> >    /* Dwarf2 Frame Description Entry, containing the Call Frame Instructions
>> >       used for unwinding.  Only set when either dwarf2 unwinding or dwarf2
>> > diff --git a/gcc/ggc-page.c b/gcc/ggc-page.c
>> > index 3939540..2a9b2d9 100644
>> > --- a/gcc/ggc-page.c
>> > +++ b/gcc/ggc-page.c
>> > @@ -500,6 +500,10 @@ static struct globals
>> >    } stats;
>> >  } G;
>> >
>> > +/* True if a gc is currently taking place.  */
>> > +
>> > +static bool in_gc = false;
>> > +
>> >  /* The size in bytes required to maintain a bitmap for the objects
>> >     on a page-entry.  */
>> >  #define BITMAP_SIZE(Num_objects) \
>> > @@ -1574,6 +1578,9 @@ ggc_get_size (const void *p)
>> >  void
>> >  ggc_free (void *p)
>> >  {
>> > +  if (in_gc)
>> > +    return;
>> > +
>> >    page_entry *pe = lookup_page_table_entry (p);
>> >    size_t order = pe->order;
>> >    size_t size = OBJECT_SIZE (order);
>> > @@ -2139,7 +2146,6 @@ ggc_collect (void)
>> >      MAX (G.allocated_last_gc, (size_t)PARAM_VALUE (GGC_MIN_HEAPSIZE) * 1024);
>> >
>> >    float min_expand = allocated_last_gc * PARAM_VALUE (GGC_MIN_EXPAND) / 100;
>> > -
>> >    if (G.allocated < allocated_last_gc + min_expand && !ggc_force_collect)
>> >      return;
>> >
>> > @@ -2162,6 +2168,7 @@ ggc_collect (void)
>> >
>> >    invoke_plugin_callbacks (PLUGIN_GGC_START, NULL);
>> >
>> > +  in_gc = true;
>> >    clear_marks ();
>> >    ggc_mark_roots ();
>> >    ggc_handle_finalizers ();
>> > @@ -2173,6 +2180,7 @@ ggc_collect (void)
>> >    validate_free_objects ();
>> >    sweep_pages ();
>> >
>> > +  in_gc = false;
>> >    G.allocated_last_gc = G.allocated;
>> >
>> >    invoke_plugin_callbacks (PLUGIN_GGC_END, NULL);
>> > diff --git a/gcc/ggc.h b/gcc/ggc.h
>> > index 1c0fd3d..6280c43 100644
>> > --- a/gcc/ggc.h
>> > +++ b/gcc/ggc.h
>> > @@ -337,4 +337,25 @@ ggc_alloc_cleared_gimple_statement_stat (size_t s CXX_MEM_STAT_INFO)
>> >      ggc_internal_cleared_alloc (s PASS_MEM_STAT);
>> >  }
>> >
>> > +static inline void
>> > +gt_ggc_mx (const char *s)
>> > +{
>> > +  ggc_test_and_set_mark (const_cast<char *> (s));
>> > +}
>> > +
>> > +static inline void
>> > +gt_pch_nx (const char *)
>> > +{
>> > +}
>> > +
>> > +static inline void
>> > +gt_ggc_mx (int)
>> > +{
>> > +}
>> > +
>> > +static inline void
>> > +gt_pch_nx (int)
>> > +{
>> > +}
>> > +
>> >  #endif
>> > diff --git a/gcc/hash-map.h b/gcc/hash-map.h
>> > index d2eed33..c65e1e5 100644
>> > --- a/gcc/hash-map.h
>> > +++ b/gcc/hash-map.h
>> > @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3.  If not see
>> >  #ifndef hash_map_h
>> >  #define hash_map_h
>> >
>> > +#include <new>
>> >  #include "hash-table.h"
>> >
>> >  /* implement default behavior for traits when types allow it.  */
>> > @@ -103,7 +104,7 @@ private:
>> >
>> >  template<typename Key, typename Value,
>> >          typename Traits = default_hashmap_traits>
>> > -class hash_map
>> > +class GTY((user)) hash_map
>> >  {
>> >    struct hash_entry
>> >    {
>> > @@ -135,10 +136,56 @@ class hash_map
>> >
>> >      static void mark_empty (hash_entry &e) { Traits::mark_empty (e); }
>> >      static bool is_empty (const hash_entry &e) { return Traits::is_empty (e); }
>> > +
>> > +    static void ggc_mx (hash_entry &e)
>> > +      {
>> > +       gt_ggc_mx (e.m_key);
>> > +       gt_ggc_mx (e.m_value);
>> > +      }
>> > +
>> > +    static void pch_nx (hash_entry &e)
>> > +      {
>> > +       gt_pch_nx (e.m_key);
>> > +       gt_pch_nx (e.m_value);
>> > +      }
>> > +
>> > +    static void pch_nx (hash_entry &e, gt_pointer_operator op, void *c)
>> > +      {
>> > +       pch_nx_helper (e.m_key, op, c);
>> > +       pch_nx_helper (e.m_value, op, c);
>> > +      }
>> > +
>> > +  private:
>> > +    template<typename T>
>> > +    static void
>> > +      pch_nx_helper (T &x, gt_pointer_operator op, void *cookie)
>> > +       {
>> > +         gt_pch_nx (&x, op, cookie);
>> > +       }
>> > +
>> > +    static void
>> > +      pch_nx_helper (int, gt_pointer_operator, void *)
>> > +       {
>> > +       }
>> > +
>> > +    template<typename T>
>> > +      static void
>> > +      pch_nx_helper (T *&x, gt_pointer_operator op, void *cookie)
>> > +       {
>> > +         op (&x, cookie);
>> > +       }
>> >    };
>> >
>> >  public:
>> > -  explicit hash_map (size_t n = 13) : m_table (n) {}
>> > +  explicit hash_map (size_t n = 13, bool ggc = false) : m_table (n, ggc) {}
>> > +
>> > +  /* Create a hash_map in ggc memory.  */
>> > +  static hash_map *create_ggc (size_t size)
>> > +    {
>> > +      hash_map *map = ggc_alloc<hash_map> ();
>> > +      new (map) hash_map (size, true);
>> > +      return map;
>> > +    }
>> >
>> >    /* If key k isn't already in the map add key k with value v to the map, and
>> >       return false.  Otherwise set the value of the entry for key k to be v and
>> > @@ -208,7 +255,35 @@ public:
>> >      }
>> >
>> >  private:
>> > +
>> > +  template<typename T, typename U, typename V> friend void gt_ggc_mx (hash_map<T, U, V> *);
>> > +  template<typename T, typename U, typename V> friend void gt_pch_nx (hash_map<T, U, V> *);
>> > +      template<typename T, typename U, typename V> friend void gt_pch_nx (hash_map<T, U, V> *, gt_pointer_operator, void *);
>> > +
>> >    hash_table<hash_entry> m_table;
>> >  };
>> >
>> > +/* ggc marking routines.  */
>> > +
>> > +template<typename K, typename V, typename H>
>> > +static inline void
>> > +gt_ggc_mx (hash_map<K, V, H> *h)
>> > +{
>> > +  gt_ggc_mx (&h->m_table);
>> > +}
>> > +
>> > +template<typename K, typename V, typename H>
>> > +static inline void
>> > +gt_pch_nx (hash_map<K, V, H> *h)
>> > +{
>> > +  gt_pch_nx (&h->m_table);
>> > +}
>> > +
>> > +template<typename K, typename V, typename H>
>> > +static inline void
>> > +gt_pch_nx (hash_map<K, V, H> *h, gt_pointer_operator op, void *cookie)
>> > +{
>> > +  op (&h->m_table.m_entries, cookie);
>> > +}
>> > +
>> >  #endif
>> > diff --git a/gcc/hash-set.h b/gcc/hash-set.h
>> > index 47bae9e..0a500cb 100644
>> > --- a/gcc/hash-set.h
>> > +++ b/gcc/hash-set.h
>> > @@ -81,6 +81,26 @@ struct default_hashset_traits
>> >    /* Return true if the passed in entry is marked as empty.  */
>> >
>> >    template<typename T> static bool is_empty (T *e) { return e == NULL; }
>> > +
>> > +  /* ggc walking routine, mark all objects refered to by this one.  */
>> > +
>> > +  template<typename T>
>> > +  static void
>> > +  ggc_mx (T &x)
>> > +    {
>> > +      extern void gt_ggc_mx (T &);
>> > +      gt_ggc_mx (x);
>> > +    }
>> > +
>> > +  /* pch walking routine, note all objects refered to by this element.  */
>> > +
>> > +  template<typename T>
>> > +  static void
>> > +  pch_nx (T &x)
>> > +    {
>> > +      extern void gt_pch_nx (T &);
>> > +      gt_pch_nx (x);
>> > +    }
>> >  };
>> >
>> >  template<typename Key, typename Traits = default_hashset_traits>
>> > @@ -128,10 +148,50 @@ class hash_set
>> >        {
>> >         return Traits::is_empty (e.m_key);
>> >        }
>> > +
>> > +    static void ggc_mx (hash_entry &e)
>> > +      {
>> > +       Traits::ggc_mx (e.m_key);
>> > +      }
>> > +
>> > +    static void pch_nx (hash_entry &e)
>> > +      {
>> > +       Traits::pch_nx (e.m_key);
>> > +      }
>> > +
>> > +    static void pch_nx (hash_entry &e, gt_pointer_operator op, void *c)
>> > +      {
>> > +       pch_nx_helper (e.m_key, op, c);
>> > +      }
>> > +
>> > +  private:
>> > +    template<typename T>
>> > +    static void
>> > +      pch_nx_helper (T &x, gt_pointer_operator op, void *cookie)
>> > +       {
>> > +         gt_pch_nx (&x, op, cookie);
>> > +       }
>> > +
>> > +    template<typename T>
>> > +      static void
>> > +      pch_nx_helper (T *&x, gt_pointer_operator op, void *cookie)
>> > +       {
>> > +         op (&x, cookie);
>> > +       }
>> >    };
>> >
>> >  public:
>> > -  explicit hash_set (size_t n = 13) : m_table (n) {}
>> > +  explicit hash_set (size_t n = 13, bool ggc = false) : m_table (n, ggc) {}
>> > +
>> > +  /* Create a hash_set in gc memory with space for at least n elements.  */
>> > +
>> > +  static hash_set *
>> > +    create_ggc (size_t n)
>> > +      {
>> > +       hash_set *set = ggc_alloc<hash_set> ();
>> > +       new (set) hash_set (n, true);
>> > +       return set;
>> > +      }
>> >
>> >    /* If key k isn't already in the map add it to the map, and
>> >       return false.  Otherwise return true.  */
>> > @@ -166,8 +226,40 @@ public:
>> >         f ((*iter).m_key, a);
>> >      }
>> >
>> > +  /* Return the number of elements in the set.  */
>> > +
>> > +  size_t elements () const { return m_table.elements (); }
>> > +
>> >  private:
>> > +
>> > +  template<typename T, typename U> friend void gt_ggc_mx (hash_set<T, U> *);
>> > +  template<typename T, typename U> friend void gt_pch_nx (hash_set<T, U> *);
>> > +      template<typename T, typename U> friend void gt_pch_nx (hash_set<T, U> *, gt_pointer_operator, void *);
>> > +
>> >    hash_table<hash_entry> m_table;
>> >  };
>> >
>> > +/* ggc marking routines.  */
>> > +
>> > +template<typename K, typename H>
>> > +static inline void
>> > +gt_ggc_mx (hash_set<K, H> *h)
>> > +{
>> > +  gt_ggc_mx (&h->m_table);
>> > +}
>> > +
>> > +template<typename K, typename H>
>> > +static inline void
>> > +gt_pch_nx (hash_set<K, H> *h)
>> > +{
>> > +  gt_pch_nx (&h->m_table);
>> > +}
>> > +
>> > +template<typename K, typename H>
>> > +static inline void
>> > +gt_pch_nx (hash_set<K, H> *h, gt_pointer_operator op, void *cookie)
>> > +{
>> > +  op (&h->m_table.m_entries, cookie);
>> > +}
>> > +
>> >  #endif
>> > diff --git a/gcc/hash-table.h b/gcc/hash-table.h
>> > index 9c6a34a..4c18786 100644
>> > --- a/gcc/hash-table.h
>> > +++ b/gcc/hash-table.h
>> > @@ -196,8 +196,11 @@ along with GCC; see the file COPYING3.  If not see
>> >  #ifndef TYPED_HASHTAB_H
>> >  #define TYPED_HASHTAB_H
>> >
>> > +#include "ggc.h"
>> >  #include "hashtab.h"
>> >
>> > +template<typename, typename, typename> class hash_map;
>> > +template<typename, typename> class hash_set;
>> >
>> >  /* The ordinary memory allocator.  */
>> >  /* FIXME (crowl): This allocator may be extracted for wider sharing later.  */
>> > @@ -998,7 +1001,7 @@ class hash_table<Descriptor, Allocator, true>
>> >    typedef typename Descriptor::compare_type compare_type;
>> >
>> >  public:
>> > -  hash_table (size_t);
>> > +  explicit hash_table (size_t, bool ggc = false);
>> >    ~hash_table ();
>> >
>> >    /* Current size (in entries) of the hash table.  */
>> > @@ -1105,6 +1108,11 @@ public:
>> >      }
>> >
>> >  private:
>> > +  template<typename T> friend void gt_ggc_mx (hash_table<T> *);
>> > +  template<typename T> friend void gt_pch_nx (hash_table<T> *);
>> > +  template<typename T> friend void hashtab_entry_note_pointers (void *, void *, gt_pointer_operator, void *);
>> > +  template<typename T, typename U, typename V> friend void gt_pch_nx (hash_map<T, U, V> *, gt_pointer_operator, void *);
>> > +  template<typename T, typename U> friend void gt_pch_nx (hash_set<T, U> *, gt_pointer_operator, void *);
>> >
>> >    value_type *find_empty_slot_for_expand (hashval_t);
>> >    void expand ();
>> > @@ -1149,18 +1157,26 @@ private:
>> >    /* Current size (in entries) of the hash table, as an index into the
>> >       table of primes.  */
>> >    unsigned int m_size_prime_index;
>> > +
>> > +  /* if m_entries is stored in ggc memory.  */
>> > +  bool m_ggc;
>> >  };
>> >
>> >  template<typename Descriptor, template<typename Type> class Allocator>
>> > -hash_table<Descriptor, Allocator, true>::hash_table (size_t size) :
>> > -  m_n_elements (0), m_n_deleted (0), m_searches (0), m_collisions (0)
>> > +hash_table<Descriptor, Allocator, true>::hash_table (size_t size, bool ggc) :
>> > +  m_n_elements (0), m_n_deleted (0), m_searches (0), m_collisions (0),
>> > +  m_ggc (ggc)
>> >  {
>> >    unsigned int size_prime_index;
>> >
>> >    size_prime_index = hash_table_higher_prime_index (size);
>> >    size = prime_tab[size_prime_index].prime;
>> >
>> > -  m_entries = Allocator <value_type> ::data_alloc (size);
>> > +  if (!m_ggc)
>> > +    m_entries = Allocator <value_type> ::data_alloc (size);
>> > +  else
>> > +    m_entries = ggc_cleared_vec_alloc<value_type> (size);
>> > +
>> >    gcc_assert (m_entries != NULL);
>> >    m_size = size;
>> >    m_size_prime_index = size_prime_index;
>> > @@ -1173,7 +1189,10 @@ hash_table<Descriptor, Allocator, true>::~hash_table ()
>> >      if (!is_empty (m_entries[i]) && !is_deleted (m_entries[i]))
>> >        Descriptor::remove (m_entries[i]);
>> >
>> > -  Allocator <value_type> ::data_free (m_entries);
>> > +  if (!m_ggc)
>> > +    Allocator <value_type> ::data_free (m_entries);
>> > +  else
>> > +    ggc_free (m_entries);
>> >  }
>> >
>> >  /* Similar to find_slot, but without several unwanted side effects:
>> > @@ -1245,7 +1264,12 @@ hash_table<Descriptor, Allocator, true>::expand ()
>> >        nsize = osize;
>> >      }
>> >
>> > -  value_type *nentries = Allocator <value_type> ::data_alloc (nsize);
>> > +  value_type *nentries;
>> > +  if (!m_ggc)
>> > +    nentries = Allocator <value_type> ::data_alloc (nsize);
>> > +  else
>> > +    nentries = ggc_cleared_vec_alloc<value_type> (nsize);
>> > +
>> >    gcc_assert (nentries != NULL);
>> >    m_entries = nentries;
>> >    m_size = nsize;
>> > @@ -1269,7 +1293,10 @@ hash_table<Descriptor, Allocator, true>::expand ()
>> >      }
>> >    while (p < olimit);
>> >
>> > -  Allocator <value_type> ::data_free (oentries);
>> > +  if (!m_ggc)
>> > +    Allocator <value_type> ::data_free (oentries);
>> > +  else
>> > +    ggc_free (oentries);
>> >  }
>> >
>> >  template<typename Descriptor, template<typename Type> class Allocator>
>> > @@ -1290,8 +1317,17 @@ hash_table<Descriptor, Allocator, true>::empty ()
>> >        int nindex = hash_table_higher_prime_index (1024 / sizeof (PTR));
>> >        int nsize = prime_tab[nindex].prime;
>> >
>> > -      Allocator <value_type> ::data_free (m_entries);
>> > -      m_entries = Allocator <value_type> ::data_alloc (nsize);
>> > +      if (!m_ggc)
>> > +       {
>> > +         Allocator <value_type> ::data_free (m_entries);
>> > +         m_entries = Allocator <value_type> ::data_alloc (nsize);
>> > +       }
>> > +      else
>> > +       {
>> > +         ggc_free (m_entries);
>> > +         m_entries = ggc_cleared_vec_alloc<value_type> (nsize);
>> > +       }
>> > +
>> >        m_size = nsize;
>> >        m_size_prime_index = nindex;
>> >      }
>> > @@ -1519,4 +1555,59 @@ hash_table<Descriptor, Allocator, true>::iterator::operator ++ ()
>> >         (ITER) != (HTAB).end () ? (RESULT = *(ITER) , true) : false; \
>> >         ++(ITER))
>> >
>> > +/* ggc walking routines.  */
>> > +
>> > +template<typename E>
>> > +static inline void
>> > +gt_ggc_mx (hash_table<E> *h)
>> > +{
>> > +  typedef hash_table<E> table;
>> > +
>> > +  if (!ggc_test_and_set_mark (h->m_entries))
>> > +    return;
>> > +
>> > +  for (size_t i = 0; i < h->m_size; i++)
>> > +    {
>> > +      if (table::is_empty (h->m_entries[i])
>> > +         || table::is_deleted (h->m_entries[i]))
>> > +       continue;
>> > +
>> > +      E::ggc_mx (h->m_entries[i]);
>> > +    }
>> > +}
>> > +
>> > +template<typename D>
>> > +static inline void
>> > +hashtab_entry_note_pointers (void *obj, void *h, gt_pointer_operator op,
>> > +                            void *cookie)
>> > +{
>> > +  hash_table<D> *map = static_cast<hash_table<D> *> (h);
>> > +  gcc_assert (map->m_entries == obj);
>> > +  for (size_t i = 0; i < map->m_size; i++)
>> > +    {
>> > +      typedef hash_table<D> table;
>> > +      if (table::is_empty (map->m_entries[i])
>> > +         || table::is_deleted (map->m_entries[i]))
>> > +       continue;
>> > +
>> > +      D::pch_nx (map->m_entries[i], op, cookie);
>> > +    }
>> > +}
>> > +
>> > +template<typename D>
>> > +static void
>> > +gt_pch_nx (hash_table<D> *h)
>> > +{
>> > +  gcc_assert (gt_pch_note_object (h->m_entries, h,
>> > +                                 hashtab_entry_note_pointers<D>));
>> > +  for (size_t i = 0; i < h->m_size; i++)
>> > +    {
>> > +      if (hash_table<D>::is_empty (h->m_entries[i])
>> > +         || hash_table<D>::is_deleted (h->m_entries[i]))
>> > +       continue;
>> > +
>> > +      D::pch_nx (h->m_entries[i]);
>> > +    }
>> > +}
>> > +
>> >  #endif /* TYPED_HASHTAB_H */
>> > diff --git a/gcc/symtab.c b/gcc/symtab.c
>> > index 739a8e4..792b3b5 100644
>> > --- a/gcc/symtab.c
>> > +++ b/gcc/symtab.c
>> > @@ -407,15 +407,7 @@ symtab_node::unregister (void)
>> >    if (!is_a <varpool_node *> (this) || !DECL_HARD_REGISTER (decl))
>> >      symtab->unlink_from_assembler_name_hash (this, false);
>> >    if (in_init_priority_hash)
>> > -    {
>> > -      symbol_priority_map in;
>> > -      void **slot;
>> > -      in.symbol = this;
>> > -
>> > -      slot = htab_find_slot (symtab->init_priority_hash, &in, NO_INSERT);
>> > -      if (slot)
>> > -       htab_clear_slot (symtab->init_priority_hash, slot);
>> > -    }
>> > +    symtab->init_priority_hash->remove (this);
>> >  }
>> >
>> >
>> > @@ -1455,14 +1447,10 @@ symtab_node::set_section (const char *section)
>> >  priority_type
>> >  symtab_node::get_init_priority ()
>> >  {
>> > -  symbol_priority_map *h;
>> > -  symbol_priority_map in;
>> > -
>> >    if (!this->in_init_priority_hash)
>> >      return DEFAULT_INIT_PRIORITY;
>> > -  in.symbol = this;
>> > -  h = (symbol_priority_map *) htab_find (symtab->init_priority_hash,
>> > -                                               &in);
>> > +
>> > +  symbol_priority_map *h = symtab->init_priority_hash->get (this);
>> >    return h ? h->init : DEFAULT_INIT_PRIORITY;
>> >  }
>> >
>> > @@ -1481,35 +1469,12 @@ enum availability symtab_node::get_availability (void)
>> >  priority_type
>> >  cgraph_node::get_fini_priority ()
>> >  {
>> > -  symbol_priority_map *h;
>> > -  symbol_priority_map in;
>> > -
>> >    if (!this->in_init_priority_hash)
>> >      return DEFAULT_INIT_PRIORITY;
>> > -  in.symbol = this;
>> > -  h = (symbol_priority_map *) htab_find (symtab->init_priority_hash,
>> > -                                               &in);
>> > +  symbol_priority_map *h = symtab->init_priority_hash->get (this);
>> >    return h ? h->fini : DEFAULT_INIT_PRIORITY;
>> >  }
>> >
>> > -/* Return true if the from tree in both priority maps are equal.  */
>> > -
>> > -int
>> > -symbol_priority_map_eq (const void *va, const void *vb)
>> > -{
>> > -  const symbol_priority_map *const a = (const symbol_priority_map *) va,
>> > -    *const b = (const symbol_priority_map *) vb;
>> > -  return (a->symbol == b->symbol);
>> > -}
>> > -
>> > -/* Hash a from symbol in a symbol_priority_map.  */
>> > -
>> > -unsigned int
>> > -symbol_priority_map_hash (const void *item)
>> > -{
>> > -  return htab_hash_pointer (((const symbol_priority_map *)item)->symbol);
>> > -}
>> > -
>> >  /* Return the initialization and finalization priority information for
>> >     DECL.  If there is no previous priority information, a freshly
>> >     allocated structure is returned.  */
>> > @@ -1517,23 +1482,14 @@ symbol_priority_map_hash (const void *item)
>> >  symbol_priority_map *
>> >  symtab_node::priority_info (void)
>> >  {
>> > -  symbol_priority_map in;
>> > -  symbol_priority_map *h;
>> > -  void **loc;
>> > -
>> > -  in.symbol = this;
>> >    if (!symtab->init_priority_hash)
>> > -    symtab->init_priority_hash = htab_create_ggc (512,
>> > -                                                 symbol_priority_map_hash,
>> > -                                                 symbol_priority_map_eq, 0);
>> > +    symtab->init_priority_hash = hash_map<symtab_node *, symbol_priority_map>::create_ggc (13);
>> >
>> > -  loc = htab_find_slot (symtab->init_priority_hash, &in, INSERT);
>> > -  h = (symbol_priority_map *) *loc;
>> > -  if (!h)
>> > +  bool existed;
>> > +  symbol_priority_map *h
>> > +    = &symtab->init_priority_hash->get_or_insert (this, &existed);
>> > +  if (!existed)
>> >      {
>> > -      h = ggc_cleared_alloc<symbol_priority_map> ();
>> > -      *loc = h;
>> > -      h->symbol = this;
>> >        h->init = DEFAULT_INIT_PRIORITY;
>> >        h->fini = DEFAULT_INIT_PRIORITY;
>> >        in_init_priority_hash = true;
>> > diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
>> > index c75516d..e89d76a 100644
>> > --- a/gcc/tree-cfg.c
>> > +++ b/gcc/tree-cfg.c
>> > @@ -4723,19 +4723,17 @@ verify_node_sharing (tree *tp, int *walk_subtrees, void *data)
>> >  }
>> >
>> >  static bool eh_error_found;
>> > -static int
>> > -verify_eh_throw_stmt_node (void **slot, void *data)
>> > +bool
>> > +verify_eh_throw_stmt_node (const gimple &stmt, const int &,
>> > +                          hash_set<gimple> *visited)
>> >  {
>> > -  struct throw_stmt_node *node = (struct throw_stmt_node *)*slot;
>> > -  hash_set<void *> *visited = (hash_set<void *> *) data;
>> > -
>> > -  if (!visited->contains (node->stmt))
>> > +  if (!visited->contains (stmt))
>> >      {
>> >        error ("dead STMT in EH table");
>> > -      debug_gimple_stmt (node->stmt);
>> > +      debug_gimple_stmt (stmt);
>> >        eh_error_found = true;
>> >      }
>> > -  return 1;
>> > +  return true;
>> >  }
>> >
>> >  /* Verify if the location LOCs block is in BLOCKS.  */
>> > @@ -4996,10 +4994,10 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
>> >      }
>> >
>> >    eh_error_found = false;
>> > -  if (get_eh_throw_stmt_table (cfun))
>> > -    htab_traverse (get_eh_throw_stmt_table (cfun),
>> > -                  verify_eh_throw_stmt_node,
>> > -                  &visited_stmts);
>> > +  hash_map<gimple, int> *eh_table = get_eh_throw_stmt_table (cfun);
>> > +  if (eh_table)
>> > +    eh_table->traverse<hash_set<gimple> *, verify_eh_throw_stmt_node>
>> > +      (&visited_stmts);
>> >
>> >    if (err || eh_error_found)
>> >      internal_error ("verify_gimple failed");
>> > diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
>> > index 6c6faf3..9da8da2 100644
>> > --- a/gcc/tree-eh.c
>> > +++ b/gcc/tree-eh.c
>> > @@ -77,23 +77,12 @@ typedef union {tree *tp; tree t; gimple g;} treemple;
>> >  static void
>> >  add_stmt_to_eh_lp_fn (struct function *ifun, gimple t, int num)
>> >  {
>> > -  struct throw_stmt_node *n;
>> > -  void **slot;
>> > -
>> >    gcc_assert (num != 0);
>> >
>> > -  n = ggc_alloc<throw_stmt_node> ();
>> > -  n->stmt = t;
>> > -  n->lp_nr = num;
>> > -
>> >    if (!get_eh_throw_stmt_table (ifun))
>> > -    set_eh_throw_stmt_table (ifun, htab_create_ggc (31, struct_ptr_hash,
>> > -                                                   struct_ptr_eq,
>> > -                                                   ggc_free));
>> > +    set_eh_throw_stmt_table (ifun, hash_map<gimple, int>::create_ggc (31));
>> >
>> > -  slot = htab_find_slot (get_eh_throw_stmt_table (ifun), n, INSERT);
>> > -  gcc_assert (!*slot);
>> > -  *slot = n;
>> > +  gcc_assert (!get_eh_throw_stmt_table (ifun)->put (t, num));
>> >  }
>> >
>> >  /* Add statement T in the current function (cfun) to EH landing pad NUM.  */
>> > @@ -130,22 +119,14 @@ record_stmt_eh_region (eh_region region, gimple t)
>> >  bool
>> >  remove_stmt_from_eh_lp_fn (struct function *ifun, gimple t)
>> >  {
>> > -  struct throw_stmt_node dummy;
>> > -  void **slot;
>> > -
>> >    if (!get_eh_throw_stmt_table (ifun))
>> >      return false;
>> >
>> > -  dummy.stmt = t;
>> > -  slot = htab_find_slot (get_eh_throw_stmt_table (ifun), &dummy,
>> > -                        NO_INSERT);
>> > -  if (slot)
>> > -    {
>> > -      htab_clear_slot (get_eh_throw_stmt_table (ifun), slot);
>> > -      return true;
>> > -    }
>> > -  else
>> > +  if (!get_eh_throw_stmt_table (ifun)->get (t))
>> >      return false;
>> > +
>> > +  get_eh_throw_stmt_table (ifun)->remove (t);
>> > +      return true;
>> >  }
>> >
>> >
>> > @@ -166,14 +147,11 @@ remove_stmt_from_eh_lp (gimple t)
>> >  int
>> >  lookup_stmt_eh_lp_fn (struct function *ifun, gimple t)
>> >  {
>> > -  struct throw_stmt_node *p, n;
>> > -
>> >    if (ifun->eh->throw_stmt_table == NULL)
>> >      return 0;
>> >
>> > -  n.stmt = t;
>> > -  p = (struct throw_stmt_node *) htab_find (ifun->eh->throw_stmt_table, &n);
>> > -  return p ? p->lp_nr : 0;
>> > +  int *lp_nr = ifun->eh->throw_stmt_table->get (t);
>> > +  return lp_nr ? *lp_nr : 0;
>> >  }
>> >
>> >  /* Likewise, but always use the current function.  */
>> > --
>> > 2.1.0
>> >
-------------- next part --------------
A non-text attachment was scrubbed...
Name: p
Type: application/octet-stream
Size: 1171 bytes
Desc: not available
URL: <http://gcc.gnu.org/pipermail/gcc-patches/attachments/20141015/d7b83535/attachment.obj>


More information about the Gcc-patches mailing list