support ggc hash_map and hash_set
authorTrevor Saunders <tsaunders@mozilla.com>
Tue, 2 Sep 2014 22:46:00 +0000 (22:46 +0000)
committerTrevor Saunders <tbsaunde@gcc.gnu.org>
Tue, 2 Sep 2014 22:46:00 +0000 (22:46 +0000)
gcc/ChangeLog:

* 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.

From-SVN: r214834

17 files changed:
gcc/ChangeLog
gcc/alloc-pool.c
gcc/cgraph.h
gcc/dbxout.c
gcc/dwarf2out.c
gcc/except.c
gcc/except.h
gcc/function.c
gcc/function.h
gcc/ggc-page.c
gcc/ggc.h
gcc/hash-map.h
gcc/hash-set.h
gcc/hash-table.h
gcc/symtab.c
gcc/tree-cfg.c
gcc/tree-eh.c

index b60054b18f63a8b9b320f3a3efdf6a6e9dfb6f39..22e69c0e7db0eb95003e1e3a5ed172bda1aef4eb 100644 (file)
@@ -1,3 +1,42 @@
+2014-09-02  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.
+
 2014-09-02  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>
 
        * config/rs6000/rs6000-builtin.def (XVCVSXDDP_SCALE):  New
index 0d3183514744f1e09f3440aa1a5883e2a2f186fb..bfaa0e4662f77821ab266cb83415af8625ca814f 100644 (file)
@@ -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"
index 879899c7d3696e471729a27b0e3e453c09a9946a..030a1c771b7c72741146ec7d3d6a2fa6c7289dcd 100644 (file)
@@ -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;
 
index 946f1d15e90cd5ad85106a284c3d425e42a4e960..d856bddc115d8fa4f3bdb1d0bbece8a587ba0dfd 100644 (file)
@@ -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);
index 7c0be8686efbb2295bef8a7b67447a875c94292a..21afc3fe21ea4123e8703b4e0ba8ead899169198 100644 (file)
@@ -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.  */
index 1f57c3f5cd833c837bc08ac8d91d0b93aede6fcc..fecc06046a231f32efa41018646a07ad7bc8f1f0 100644 (file)
@@ -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;
 }
 \f
-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);
 }
 
 \f
@@ -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;
index 71a8dceba8af390ffa56e0a9ab5a7482fef815b4..325915132048cd22a54b2468a8b24655ac0fb2c4 100644 (file)
@@ -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,
index 464c6cdaa57771c842254b73b99e118f30dab116..2e46799f751076d7d88591b015cd0b1609c87e3c 100644 (file)
@@ -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);
     }
 }
 
index 071f5dd237c1c512111ff3fcf0339674998826da..e71210df350acf0bc3721fcab70aa306dbb83b40 100644 (file)
@@ -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
index 393954089f8bfd9a96277f443a4e9543cd3f2b02..2a9b2d9e7fa4d7cc2aa148f134433dd5098dfdf3 100644 (file)
@@ -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);
index 1c0fd3d1ba5e8c00cc9960f3e2dd4be78f2d8599..6280c433809944d57d38ff271d6616941c8f6628 100644 (file)
--- 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
index d2eed337ad4530ed9484cba927f80a955b5f8afd..c65e1e57999776d818ecc390e6afe6b7bc86d08a 100644 (file)
@@ -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
index 47bae9ed77d4604c58cc8622e62693cd7335d1a2..0a500cb441ab3fe3565442bba0655259bfffa418 100644 (file)
@@ -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
index 9c6a34ad70b22ab65f9147f1a19da59654bd633f..c2a68fd23a2bc7ebd54cb0cde6c4593b4fcf6766 100644 (file)
@@ -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_checking_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_checking_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 */
index 739a8e4a308df4a0851498759bb7743fe3efd0ed..792b3b50ea6a04bf1ea228a6201475df825c3c45 100644 (file)
@@ -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;
index c75516db112290ce45dfcdd9a773084f7aa21bcd..e89d76a015aaf4e8e4bacec3cbcef1b9b03620d6 100644 (file)
@@ -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");
index 6c6faf303644cef8cc1962a77250d01241aadbf4..9da8da28b3656e1d774441dfb9dd8972f77d3600 100644 (file)
@@ -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.  */