From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 8782 invoked by alias); 17 Oct 2014 13:31:19 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 8767 invoked by uid 89); 17 Oct 2014 13:31:18 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=1.7 required=5.0 tests=AWL,BAYES_00,KAM_STOCKTIP,SPF_PASS autolearn=no version=3.3.2 X-HELO: service87.mimecast.com Received: from service87.mimecast.com (HELO service87.mimecast.com) (91.220.42.44) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 17 Oct 2014 13:31:14 +0000 Received: from cam-owa1.Emea.Arm.com (fw-tnat.cambridge.arm.com [217.140.96.21]) by service87.mimecast.com; Fri, 17 Oct 2014 14:31:02 +0100 Received: from [10.1.209.51] ([10.1.255.212]) by cam-owa1.Emea.Arm.com with Microsoft SMTPSVC(6.0.3790.3959); Fri, 17 Oct 2014 14:30:57 +0100 Message-ID: <54411A11.8060001@arm.com> Date: Fri, 17 Oct 2014 13:36:00 -0000 From: Alan Lawrence User-Agent: Thunderbird 2.0.0.24 (X11/20101213) MIME-Version: 1.0 To: Trevor Saunders CC: "gcc-patches@gcc.gnu.org" Subject: Re: [PATCH] support ggc hash_map and hash_set References: <1409622988-14529-1-git-send-email-tsaunders@mozilla.com> <540F10A6.5010807@arm.com> <20140910021254.GA31208@tsaunders-iceball.corp.tor1.mozilla.com> In-Reply-To: <20140910021254.GA31208@tsaunders-iceball.corp.tor1.mozilla.com> X-MC-Unique: 114101714310220501 Content-Type: text/plain; charset=WINDOWS-1252; format=flowed Content-Transfer-Encoding: quoted-printable X-IsSubscribed: yes X-SW-Source: 2014-10/txt/msg01723.txt.bz2 Sorry, somehow I missed this email. Yes, that appears to have fixed it! Thank you very much, Alan Trevor Saunders wrote: > 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 A= RM >> (aarch64-none-elf, aarch64_be-none-elf and arm-none-eabi; I haven't test= ed >> armeb-none-eabi; builds targeting linux are OK), for *release builds onl= y*. >=20 > Could you test the below patch? it seems to work for me, but I'm not > familiar with testing cross compilers. >=20 > 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 > static void > gt_pch_nx (hash_table *h) > { > - gcc_checking_assert (gt_pch_note_object (h->m_entries, h, > - hashtab_entry_note_pointers= )); > + bool success ATTRIBUTE_UNUSED > + =3D gt_pch_note_object (h->m_entries, h, hashtab_entry_note_pointers= ); > + gcc_checking_assert (success); > for (size_t i =3D 0; i < h->m_size; i++) > { > if (hash_table::is_empty (h->m_entries[i]) >=20 > Trev >=20 >> 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 correspon= ding >> 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=3Dnever -nostdinc++ >> -Ibuild/obj/gcc2/aarch64-none-elf/ilp32/libstdc++-v3/include/aarch64-non= e-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=3D0 -O2 -g >> -specs=3Daem-ve.specs -mabi=3Dilp32 -mcmodel=3Dsmall -o template-1.H= .gch >> (timeout =3D 300) >> spawn build/obj/gcc2/gcc/testsuite/g++/../../xg++ >> -Bbuild/obj/gcc2/gcc/testsuite/g++/../../ ./template-1.H >> -fno-diagnostics-show-caret -fdiagnostics-color=3Dnever -nostdinc++ >> -Ibuild/obj/gcc2/aarch64-none-elf/ilp32/libstdc++-v3/include/aarch64-non= e-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=3D0 -O2 -g >> -specs=3Daem-ve.specs -mabi=3Dilp32 -mcmodel=3Dsmall -o template-1.H.gch >> >> ./template-1.H:5:2: internal compiler error: in relocate_ptrs, at ggc-co= mmon.c:435 >> Please submit a full bug report, >> with preprocessed source if appropriate. >> See for instructions. >> compiler exited with status 1 >> output is: >> ./array-1.H:4:2: internal compiler error: in relocate_ptrs, at ggc-commo= n.c:435 >> Please submit a full bug report, >> with preprocessed source if appropriate. >> See 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-commo= n.c:435 >> >> --Alan >> >> tsaunders@mozilla.com wrote: >>> From: Trevor Saunders >>> >>> Hi, >>> >>> There are still some issues to make this work really nicely, but this p= art 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 breaki= ng other >>> front ends. However that seems to be an unrelated issue you can trigge= r 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 trait= s 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-gn= u, ok? >>> >>> Trev >>> >>> gcc/ChangeLog: >>> >>> 2014-09-01 Trevor Saunders >>> >>> * 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 *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 *types_p) >>> { >>> - tree type =3D (tree) *slot; >>> - vec *types_p =3D (vec *) data; >>> - >>> if ((TREE_CODE (type) =3D=3D RECORD_TYPE >>> || TREE_CODE (type) =3D=3D UNION_TYPE >>> || TREE_CODE (type) =3D=3D QUAL_UNION_TYPE >>> @@ -2502,7 +2499,7 @@ output_used_types_helper (void **slot, void *data) >>> && TREE_CODE (TYPE_NAME (type)) =3D=3D 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 *, output_used_types_h= elper> >>> + (&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 =3D (tree) *slot; >>> die =3D lookup_type_die (type); >>> if (die !=3D NULL) >>> die->die_perennial_p =3D 1; >>> - return 1; >>> + return true; >>> } >>> >>> /* Helper function of premark_types_used_by_global_vars which gets call= ed >>> @@ -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, NU= LL); >>> + fun->used_types_hash->traverse = (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 *type_to_runtim= e_map; >>> >>> /* Describe the SjLj_Function_Context structure. */ >>> static GTY(()) tree sjlj_fc_type_node; >>> @@ -213,9 +218,6 @@ typedef hash_table action_has= h_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 =3D htab_create_ggc (31, t2r_hash, t2r_eq, NULL); >>> + type_to_runtime_map >>> + =3D hash_map::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_re= gion region_a, >>> return region_a; >>> } >>> >>> -static int >>> -t2r_eq (const void *pentry, const void *pdata) >>> -{ >>> - const_tree const entry =3D (const_tree) pentry; >>> - const_tree const data =3D (const_tree) pdata; >>> - >>> - return TREE_PURPOSE (entry) =3D=3D data; >>> -} >>> - >>> -static hashval_t >>> -t2r_hash (const void *pentry) >>> -{ >>> - const_tree const entry =3D (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) =3D=3D NOP_EXPR) >>> return; >>> >>> - slot =3D (tree *) htab_find_slot_with_hash (type_to_runtime_map, typ= e, >>> - TREE_HASH (type), INSERT); >>> - if (*slot =3D=3D NULL) >>> - { >>> - tree runtime =3D lang_hooks.eh_runtime_type (type); >>> - *slot =3D tree_cons (type, runtime, NULL_TREE); >>> - } >>> + bool existed =3D false; >>> + tree *slot =3D &type_to_runtime_map->get_or_insert (type, &existed); >>> + if (!existed) >>> + *slot =3D 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) =3D=3D NOP_EXPR) >>> return type; >>> >>> - slot =3D (tree *) htab_find_slot_with_hash (type_to_runtime_map, typ= e, >>> - 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 *fn= name) >>> } >>> >>> void >>> -set_eh_throw_stmt_table (struct function *fun, struct htab *table) >>> +set_eh_throw_stmt_table (function *fun, hash_map *table) >>> { >>> fun->eh->throw_stmt_table =3D table; >>> } >>> >>> -htab_t >>> +hash_map * >>> 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 *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 *get_eh_throw_stmt_table (struct function= *); >>> +extern void set_eh_throw_stmt_table (function *, hash_map= *); >>> >>> 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 fun= ction *func) >>> { >>> if (type !=3D NULL && func !=3D NULL) >>> { >>> - void **slot; >>> - >>> if (func->used_types_hash =3D=3D NULL) >>> - func->used_types_hash =3D htab_create_ggc (37, htab_hash_pointe= r, >>> - htab_eq_pointer, NULL); >>> - slot =3D htab_find_slot (func->used_types_hash, type, INSERT); >>> - if (*slot =3D=3D NULL) >>> - *slot =3D type; >>> + func->used_types_hash =3D hash_set::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 *GTY (()) used_types_hash; >>> >>> /* Dwarf2 Frame Description Entry, containing the Call Frame Instruct= ions >>> used for unwinding. Only set when either dwarf2 unwinding or dwar= f2 >>> 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 =3D 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 =3D lookup_page_table_entry (p); >>> size_t order =3D pe->order; >>> size_t size =3D 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 =3D allocated_last_gc * PARAM_VALUE (GGC_MIN_EXPAND)= / 100; >>> - >>> if (G.allocated < allocated_last_gc + min_expand && !ggc_force_collec= t) >>> return; >>> >>> @@ -2162,6 +2168,7 @@ ggc_collect (void) >>> >>> invoke_plugin_callbacks (PLUGIN_GGC_START, NULL); >>> >>> + in_gc =3D true; >>> clear_marks (); >>> ggc_mark_roots (); >>> ggc_handle_finalizers (); >>> @@ -2173,6 +2180,7 @@ ggc_collect (void) >>> validate_free_objects (); >>> sweep_pages (); >>> >>> + in_gc =3D false; >>> G.allocated_last_gc =3D 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 (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 >>> #include "hash-table.h" >>> >>> /* implement default behavior for traits when types allow it. */ >>> @@ -103,7 +104,7 @@ private: >>> >>> template>> typename Traits =3D 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_empt= y (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 >>> + 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 >>> + static void >>> + pch_nx_helper (T *&x, gt_pointer_operator op, void *cookie) >>> + { >>> + op (&x, cookie); >>> + } >>> }; >>> >>> public: >>> - explicit hash_map (size_t n =3D 13) : m_table (n) {} >>> + explicit hash_map (size_t n =3D 13, bool ggc =3D false) : m_table (n= , ggc) {} >>> + >>> + /* Create a hash_map in ggc memory. */ >>> + static hash_map *create_ggc (size_t size) >>> + { >>> + hash_map *map =3D ggc_alloc (); >>> + 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 ma= p, and >>> return false. Otherwise set the value of the entry for key k to b= e v and >>> @@ -208,7 +255,35 @@ public: >>> } >>> >>> private: >>> + >>> + template friend void gt_ggc_mx (= hash_map *); >>> + template friend void gt_pch_nx (= hash_map *); >>> + template friend void gt_pch_= nx (hash_map *, gt_pointer_operator, void *); >>> + >>> hash_table m_table; >>> }; >>> >>> +/* ggc marking routines. */ >>> + >>> +template >>> +static inline void >>> +gt_ggc_mx (hash_map *h) >>> +{ >>> + gt_ggc_mx (&h->m_table); >>> +} >>> + >>> +template >>> +static inline void >>> +gt_pch_nx (hash_map *h) >>> +{ >>> + gt_pch_nx (&h->m_table); >>> +} >>> + >>> +template >>> +static inline void >>> +gt_pch_nx (hash_map *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 static bool is_empty (T *e) { return e =3D=3D NU= LL; } >>> + >>> + /* ggc walking routine, mark all objects refered to by this one. */ >>> + >>> + template >>> + 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 >>> + static void >>> + pch_nx (T &x) >>> + { >>> + extern void gt_pch_nx (T &); >>> + gt_pch_nx (x); >>> + } >>> }; >>> >>> template >>> @@ -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 >>> + static void >>> + pch_nx_helper (T &x, gt_pointer_operator op, void *cookie) >>> + { >>> + gt_pch_nx (&x, op, cookie); >>> + } >>> + >>> + template >>> + static void >>> + pch_nx_helper (T *&x, gt_pointer_operator op, void *cookie) >>> + { >>> + op (&x, cookie); >>> + } >>> }; >>> >>> public: >>> - explicit hash_set (size_t n =3D 13) : m_table (n) {} >>> + explicit hash_set (size_t n =3D 13, bool ggc =3D 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 =3D ggc_alloc (); >>> + 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 friend void gt_ggc_mx (hash_set *); >>> + template friend void gt_pch_nx (hash_set *); >>> + template friend void gt_pch_nx (hash_set= *, gt_pointer_operator, void *); >>> + >>> hash_table m_table; >>> }; >>> >>> +/* ggc marking routines. */ >>> + >>> +template >>> +static inline void >>> +gt_ggc_mx (hash_set *h) >>> +{ >>> + gt_ggc_mx (&h->m_table); >>> +} >>> + >>> +template >>> +static inline void >>> +gt_pch_nx (hash_set *h) >>> +{ >>> + gt_pch_nx (&h->m_table); >>> +} >>> + >>> +template >>> +static inline void >>> +gt_pch_nx (hash_set *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 class hash_map; >>> +template class hash_set; >>> >>> /* The ordinary memory allocator. */ >>> /* FIXME (crowl): This allocator may be extracted for wider sharing lat= er. */ >>> @@ -998,7 +1001,7 @@ class hash_table >>> typedef typename Descriptor::compare_type compare_type; >>> >>> public: >>> - hash_table (size_t); >>> + explicit hash_table (size_t, bool ggc =3D false); >>> ~hash_table (); >>> >>> /* Current size (in entries) of the hash table. */ >>> @@ -1105,6 +1108,11 @@ public: >>> } >>> >>> private: >>> + template friend void gt_ggc_mx (hash_table *); >>> + template friend void gt_pch_nx (hash_table *); >>> + template friend void hashtab_entry_note_pointers (void *= , void *, gt_pointer_operator, void *); >>> + template friend void gt_pch_nx (= hash_map *, gt_pointer_operator, void *); >>> + template friend void gt_pch_nx (hash_set *, 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 class Allocator> >>> -hash_table::hash_table (size_t size) : >>> - m_n_elements (0), m_n_deleted (0), m_searches (0), m_collisions (0) >>> +hash_table::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 =3D hash_table_higher_prime_index (size); >>> size =3D prime_tab[size_prime_index].prime; >>> >>> - m_entries =3D Allocator ::data_alloc (size); >>> + if (!m_ggc) >>> + m_entries =3D Allocator ::data_alloc (size); >>> + else >>> + m_entries =3D ggc_cleared_vec_alloc (size); >>> + >>> gcc_assert (m_entries !=3D NULL); >>> m_size =3D size; >>> m_size_prime_index =3D size_prime_index; >>> @@ -1173,7 +1189,10 @@ hash_table::~hash_t= able () >>> if (!is_empty (m_entries[i]) && !is_deleted (m_entries[i])) >>> Descriptor::remove (m_entries[i]); >>> >>> - Allocator ::data_free (m_entries); >>> + if (!m_ggc) >>> + Allocator ::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::expand = () >>> nsize =3D osize; >>> } >>> >>> - value_type *nentries =3D Allocator ::data_alloc (nsize); >>> + value_type *nentries; >>> + if (!m_ggc) >>> + nentries =3D Allocator ::data_alloc (nsize); >>> + else >>> + nentries =3D ggc_cleared_vec_alloc (nsize); >>> + >>> gcc_assert (nentries !=3D NULL); >>> m_entries =3D nentries; >>> m_size =3D nsize; >>> @@ -1269,7 +1293,10 @@ hash_table::expand = () >>> } >>> while (p < olimit); >>> >>> - Allocator ::data_free (oentries); >>> + if (!m_ggc) >>> + Allocator ::data_free (oentries); >>> + else >>> + ggc_free (oentries); >>> } >>> >>> template class Allocator> >>> @@ -1290,8 +1317,17 @@ hash_table::empty () >>> int nindex =3D hash_table_higher_prime_index (1024 / sizeof (PTR)= ); >>> int nsize =3D prime_tab[nindex].prime; >>> >>> - Allocator ::data_free (m_entries); >>> - m_entries =3D Allocator ::data_alloc (nsize); >>> + if (!m_ggc) >>> + { >>> + Allocator ::data_free (m_entries); >>> + m_entries =3D Allocator ::data_alloc (nsize); >>> + } >>> + else >>> + { >>> + ggc_free (m_entries); >>> + m_entries =3D ggc_cleared_vec_alloc (nsize); >>> + } >>> + >>> m_size =3D nsize; >>> m_size_prime_index =3D nindex; >>> } >>> @@ -1519,4 +1555,59 @@ hash_table::iterato= r::operator ++ () >>> (ITER) !=3D (HTAB).end () ? (RESULT =3D *(ITER) , true) : false;= \ >>> ++(ITER)) >>> >>> +/* ggc walking routines. */ >>> + >>> +template >>> +static inline void >>> +gt_ggc_mx (hash_table *h) >>> +{ >>> + typedef hash_table table; >>> + >>> + if (!ggc_test_and_set_mark (h->m_entries)) >>> + return; >>> + >>> + for (size_t i =3D 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 >>> +static inline void >>> +hashtab_entry_note_pointers (void *obj, void *h, gt_pointer_operator o= p, >>> + void *cookie) >>> +{ >>> + hash_table *map =3D static_cast *> (h); >>> + gcc_assert (map->m_entries =3D=3D obj); >>> + for (size_t i =3D 0; i < map->m_size; i++) >>> + { >>> + typedef hash_table 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 >>> +static void >>> +gt_pch_nx (hash_table *h) >>> +{ >>> + gcc_assert (gt_pch_note_object (h->m_entries, h, >>> + hashtab_entry_note_pointers)); >>> + for (size_t i =3D 0; i < h->m_size; i++) >>> + { >>> + if (hash_table::is_empty (h->m_entries[i]) >>> + || hash_table::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 (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 =3D this; >>> - >>> - slot =3D htab_find_slot (symtab->init_priority_hash, &in, NO_INS= ERT); >>> - 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 =3D this; >>> - h =3D (symbol_priority_map *) htab_find (symtab->init_priority_hash, >>> - &in); >>> + >>> + symbol_priority_map *h =3D 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 =3D this; >>> - h =3D (symbol_priority_map *) htab_find (symtab->init_priority_hash, >>> - &in); >>> + symbol_priority_map *h =3D 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 =3D (const symbol_priority_map *)= va, >>> - *const b =3D (const symbol_priority_map *) vb; >>> - return (a->symbol =3D=3D 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)->symbo= l); >>> -} >>> - >>> /* 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 =3D this; >>> if (!symtab->init_priority_hash) >>> - symtab->init_priority_hash =3D htab_create_ggc (512, >>> - symbol_priority_map_h= ash, >>> - symbol_priority_map_e= q, 0); >>> + symtab->init_priority_hash =3D hash_map::create_ggc (13); >>> >>> - loc =3D htab_find_slot (symtab->init_priority_hash, &in, INSERT); >>> - h =3D (symbol_priority_map *) *loc; >>> - if (!h) >>> + bool existed; >>> + symbol_priority_map *h >>> + =3D &symtab->init_priority_hash->get_or_insert (this, &existed); >>> + if (!existed) >>> { >>> - h =3D ggc_cleared_alloc (); >>> - *loc =3D h; >>> - h->symbol =3D this; >>> h->init =3D DEFAULT_INIT_PRIORITY; >>> h->fini =3D DEFAULT_INIT_PRIORITY; >>> in_init_priority_hash =3D 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_subtre= es, 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 *visited) >>> { >>> - struct throw_stmt_node *node =3D (struct throw_stmt_node *)*slot; >>> - hash_set *visited =3D (hash_set *) 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 =3D 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 =3D 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 *eh_table =3D get_eh_throw_stmt_table (cfun); >>> + if (eh_table) >>> + eh_table->traverse *, 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;} treempl= e; >>> 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 !=3D 0); >>> >>> - n =3D ggc_alloc (); >>> - n->stmt =3D t; >>> - n->lp_nr =3D num; >>> - >>> if (!get_eh_throw_stmt_table (ifun)) >>> - set_eh_throw_stmt_table (ifun, htab_create_ggc (31, struct_ptr_has= h, >>> - struct_ptr_eq, >>> - ggc_free)); >>> + set_eh_throw_stmt_table (ifun, hash_map::create_ggc (= 31)); >>> >>> - slot =3D htab_find_slot (get_eh_throw_stmt_table (ifun), n, INSERT); >>> - gcc_assert (!*slot); >>> - *slot =3D 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 =3D t; >>> - slot =3D 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 =3D=3D NULL) >>> return 0; >>> >>> - n.stmt =3D t; >>> - p =3D (struct throw_stmt_node *) htab_find (ifun->eh->throw_stmt_tab= le, &n); >>> - return p ? p->lp_nr : 0; >>> + int *lp_nr =3D ifun->eh->throw_stmt_table->get (t); >>> + return lp_nr ? *lp_nr : 0; >>> } >>> >>> /* Likewise, but always use the current function. */ >>> -- >>> 2.1.0 >=20