This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] support ggc hash_map and hash_set


On Tue, Sep 09, 2014 at 03:37:26PM +0100, Alan Lawrence wrote:
> Following this, we're seeing ICEs in tests in gcc.dg/pch.exp and g++.dg/pch.exp,
> with cross-builds (hosted on x86_64) targetting bare metal AArch64 and ARM
> (aarch64-none-elf, aarch64_be-none-elf and arm-none-eabi; I haven't tested
> armeb-none-eabi; builds targeting linux are OK), for *release builds only*.

Could you test the below patch? it seems to work for me, but I'm not
familiar with testing cross compilers.

diff --git a/gcc/hash-table.h b/gcc/hash-table.h
index c2a68fd..028b7de 100644
--- a/gcc/hash-table.h
+++ b/gcc/hash-table.h
@@ -1598,8 +1598,9 @@ 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>));
+  bool success ATTRIBUTE_UNUSED
+    = gt_pch_note_object (h->m_entries, h, hashtab_entry_note_pointers<D>);
+  gcc_checking_assert (success);
   for (size_t i = 0; i < h->m_size; i++)
     {
       if (hash_table<D>::is_empty (h->m_entries[i])

       Trev

> 
> Affected tests:
> 
> gcc.dg/pch.exp: all variants of
> ./except-1.h
> ./inline-3.h
> gcc.dg/pch/except-1.c
> gcc.dg/pch/inline-3.c
> 
> g++.dg: all variants of
> ./array-1.H
> ./empty.H
> ./externc-1.H
> ./local-1.H
> ./pch.H
> ./static-1.H
> ./system-1.H
> ./system-2.H
> ./template-1.H
> ./uninst.H
> ./wchar-1.H
> 
> (These then lead to failures of g++.dg/pch/{array-1,...}.C and corresponding
> assembly comparisons).
> 
> Sample log:
> 
> Executing on host: build/obj/gcc2/gcc/testsuite/g++/../../xg++
> -Bbuild/obj/gcc2/gcc/testsuite/g++/../../ ./template-1.H
> -fno-diagnostics-show-caret -fdiagnostics-color=never  -nostdinc++
> -Ibuild/obj/gcc2/aarch64-none-elf/ilp32/libstdc++-v3/include/aarch64-none-elf
> -Ibuild/obj/gcc2/aarch64-none-elf/ilp32/libstdc++-v3/include
> -Isrc/gcc/libstdc++-v3/libsupc++ -Isrc/gcc/libstdc++-v3/include/backward
> -Isrc/gcc/libstdc++-v3/testsuite/util -fmessage-length=0  -O2 -g
> -specs=aem-ve.specs    -mabi=ilp32 -mcmodel=small  -o template-1.H.gch
> (timeout = 300)
> spawn build/obj/gcc2/gcc/testsuite/g++/../../xg++
> -Bbuild/obj/gcc2/gcc/testsuite/g++/../../ ./template-1.H
> -fno-diagnostics-show-caret -fdiagnostics-color=never -nostdinc++
> -Ibuild/obj/gcc2/aarch64-none-elf/ilp32/libstdc++-v3/include/aarch64-none-elf
> -Ibuild/obj/gcc2/aarch64-none-elf/ilp32/libstdc++-v3/include
> -Isrc/gcc/libstdc++-v3/libsupc++ -Isrc/gcc/libstdc++-v3/include/backward
> -Isrc/gcc/libstdc++-v3/testsuite/util -fmessage-length=0 -O2 -g
> -specs=aem-ve.specs -mabi=ilp32 -mcmodel=small -o template-1.H.gch
> 
> ./template-1.H:5:2: internal compiler error: in relocate_ptrs, at ggc-common.c:435
> Please submit a full bug report,
> with preprocessed source if appropriate.
> See <http://gcc.gnu.org/bugs.html> for instructions.
> compiler exited with status 1
> output is:
> ./array-1.H:4:2: internal compiler error: in relocate_ptrs, at ggc-common.c:435
> Please submit a full bug report,
> with preprocessed source if appropriate.
> See <http://gcc.gnu.org/bugs.html> for instructions.
> 
> FAIL: ./array-1.H  -g (internal compiler error)
> FAIL: ./array-1.H  -g (test for excess errors)
> Excess errors:
> ./array-1.H:4:2: internal compiler error: in relocate_ptrs, at ggc-common.c:435
> 
> --Alan
> 
> 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?
> >
> >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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]