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 > > tsaund...@mozilla.com wrote: > >From: Trevor Saunders <tsaund...@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 <tsaund...@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