From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 22649 invoked by alias); 15 Oct 2014 07:32:39 -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 22637 invoked by uid 89); 15 Oct 2014 07:32:38 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=4.4 required=5.0 tests=AWL,BAYES_99,BAYES_999,FREEMAIL_FROM,KAM_STOCKTIP,RCVD_IN_DNSWL_LOW,SPF_PASS autolearn=no version=3.3.2 X-HELO: mail-wi0-f180.google.com Received: from mail-wi0-f180.google.com (HELO mail-wi0-f180.google.com) (209.85.212.180) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Wed, 15 Oct 2014 07:32:35 +0000 Received: by mail-wi0-f180.google.com with SMTP id em10so1038519wid.13 for ; Wed, 15 Oct 2014 00:32:31 -0700 (PDT) MIME-Version: 1.0 X-Received: by 10.194.81.6 with SMTP id v6mr10096428wjx.39.1413358351849; Wed, 15 Oct 2014 00:32:31 -0700 (PDT) Received: by 10.194.20.74 with HTTP; Wed, 15 Oct 2014 00:32:31 -0700 (PDT) In-Reply-To: <20141015025724.GA27908@tsaunders-iceball.corp.tor1.mozilla.com> References: <1409622988-14529-1-git-send-email-tsaunders@mozilla.com> <20141015025724.GA27908@tsaunders-iceball.corp.tor1.mozilla.com> Date: Wed, 15 Oct 2014 07:34:00 -0000 Message-ID: Subject: Re: [PATCH] support ggc hash_map and hash_set From: Richard Biener To: Trevor Saunders Cc: GCC Patches Content-Type: multipart/mixed; boundary=047d7bea3de680b2c40505712211 X-IsSubscribed: yes X-SW-Source: 2014-10/txt/msg01308.txt.bz2 --047d7bea3de680b2c40505712211 Content-Type: text/plain; charset=UTF-8 Content-length: 38581 On Wed, Oct 15, 2014 at 4:57 AM, Trevor Saunders wrote: > On Tue, Oct 14, 2014 at 04:05:25PM +0200, Richard Biener wrote: >> On Tue, Sep 2, 2014 at 3:56 AM, wrote: >> > From: Trevor Saunders >> > >> > Hi, >> > >> > There are still some issues to make this work really nicely, but this part is >> > probably good enough its worth reviewing. >> > >> > For one thing you can't use ggc hash_map or set in front ends with some types >> > or gengtype will decide to put the overloads of the marking routines it >> > provides in a front end file instead of the one it choose before breaking other >> > front ends. However that seems to be an unrelated issue you can trigger it >> > without using hash_map/set, so we might as well solve it separetly. >> > >> > I had to have the entry marking functions for set deligate to the traits class >> > because gcc < 4.9.1 issues clearly bogus errors if you inline the code from the >> > traits implementation. We may well want to make map work the same way at some >> > point to enable some of the special GTY attributes like if_marked, but it >> > doesn't seem to be necessary right now. >> > >> > bootstrapped + regtested without regressions on x86_64-unknown-linux-gnu, ok? >> >> I have just noticed that this (ggc support for hash-table.h) makes it no longer >> suitable for use from generator programs (trying to merge from trunk on >> match-and-simplify). If you look at vec.h it has sophisticated guards >> to block out GGC support if GENERATOR_FILE is defined. > > yeah, it works, but its kind of messy since some of the generator > programs include ggc.h. > >> Can you try to fix this please? > > I expect its doable, I can try to get it done later this week / week > end, but next few days are busy for me. Something as simple as the following works for me on the branch (but maybe too hackish to declare but not define the ggc alloc templates). Richard. > Trev > >> >> Thanks, >> Richard. >> >> > Trev >> > >> > gcc/ChangeLog: >> > >> > 2014-09-01 Trevor Saunders >> > >> > * 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 = (tree) *slot; >> > - vec *types_p = (vec *) 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 *, 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 (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_runtime_map; >> > >> > /* Describe the SjLj_Function_Context structure. */ >> > static GTY(()) tree sjlj_fc_type_node; >> > @@ -213,9 +218,6 @@ typedef hash_table 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::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 *table) >> > { >> > fun->eh->throw_stmt_table = 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 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::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 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 (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 = 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 >> > + 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 = 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 (); >> > + 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 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 == NULL; } >> > + >> > + /* 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 = 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 (); >> > + 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 later. */ >> > @@ -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 = 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 = hash_table_higher_prime_index (size); >> > size = prime_tab[size_prime_index].prime; >> > >> > - m_entries = Allocator ::data_alloc (size); >> > + if (!m_ggc) >> > + m_entries = Allocator ::data_alloc (size); >> > + else >> > + m_entries = ggc_cleared_vec_alloc (size); >> > + >> > gcc_assert (m_entries != NULL); >> > m_size = size; >> > m_size_prime_index = size_prime_index; >> > @@ -1173,7 +1189,10 @@ hash_table::~hash_table () >> > 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 = osize; >> > } >> > >> > - value_type *nentries = Allocator ::data_alloc (nsize); >> > + value_type *nentries; >> > + if (!m_ggc) >> > + nentries = Allocator ::data_alloc (nsize); >> > + else >> > + nentries = ggc_cleared_vec_alloc (nsize); >> > + >> > gcc_assert (nentries != NULL); >> > m_entries = nentries; >> > m_size = 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 = hash_table_higher_prime_index (1024 / sizeof (PTR)); >> > int nsize = prime_tab[nindex].prime; >> > >> > - Allocator ::data_free (m_entries); >> > - m_entries = Allocator ::data_alloc (nsize); >> > + if (!m_ggc) >> > + { >> > + Allocator ::data_free (m_entries); >> > + m_entries = Allocator ::data_alloc (nsize); >> > + } >> > + else >> > + { >> > + ggc_free (m_entries); >> > + m_entries = ggc_cleared_vec_alloc (nsize); >> > + } >> > + >> > m_size = nsize; >> > m_size_prime_index = nindex; >> > } >> > @@ -1519,4 +1555,59 @@ hash_table::iterator::operator ++ () >> > (ITER) != (HTAB).end () ? (RESULT = *(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 = 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 op, >> > + void *cookie) >> > +{ >> > + hash_table *map = static_cast *> (h); >> > + gcc_assert (map->m_entries == obj); >> > + for (size_t i = 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 = 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 = 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::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 (); >> > - *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 *visited) >> > { >> > - struct throw_stmt_node *node = (struct throw_stmt_node *)*slot; >> > - hash_set *visited = (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 = 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 *eh_table = 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;} 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 (); >> > - 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::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 >> > --047d7bea3de680b2c40505712211 Content-Type: application/octet-stream; name=p Content-Disposition: attachment; filename=p Content-Transfer-Encoding: base64 X-Attachment-Id: f_i1acx8jo0 Content-length: 1591 MjAxNC0xMC0xNSAgUmljaGFyZCBCaWVuZXIgIDxyZ3VlbnRoZXJAc3VzZS5k ZT4KCgkqIGhhc2gtdGFibGUuYzogSW5jbHVkZSBiY29uZmlnLmggaWYgYnVp bGRpbmcgZm9yIHRoZSBob3N0LgoJKiBoYXNoLXRhYmxlLmg6IERvIG5vdCBp bmNsdWRlIGdnYy5oIG9uIHRoZSBob3N0IGJ1dCBqdXN0IGRlY2xhcmUKCWEg ZmV3IGdnYyBhbGxvY2F0aW9uIHRlbXBsYXRlcy4KCkluZGV4OiBnY2MvaGFz aC10YWJsZS5jCj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KLS0tIGdjYy9oYXNo LXRhYmxlLmMJKHJldmlzaW9uIDIxNjIwMSkKKysrIGdjYy9oYXNoLXRhYmxl LmMJKHdvcmtpbmcgY29weSkKQEAgLTIyLDcgKzIyLDExIEBAIGFsb25nIHdp dGggR0NDOyBzZWUgdGhlIGZpbGUgQ09QWUlORzMuCiAvKiBUaGlzIGZpbGUg aW1wbGVtZW50cyBhIHR5cGVkIGhhc2ggdGFibGUuCiAgICBUaGUgaW1wbGVt ZW50YXRpb24gYm9ycm93cyBmcm9tIGxpYmliZXJ0eSdzIGhhc2h0YWIuICAq LwogCisjaWZkZWYgR0VORVJBVE9SX0ZJTEUKKyNpbmNsdWRlICJiY29uZmln LmgiCisjZWxzZQogI2luY2x1ZGUgImNvbmZpZy5oIgorI2VuZGlmCiAjaW5j bHVkZSAic3lzdGVtLmgiCiAjaW5jbHVkZSAiY29yZXR5cGVzLmgiCiAjaW5j bHVkZSAiaGFzaC10YWJsZS5oIgpJbmRleDogZ2NjL2hhc2gtdGFibGUuaAo9 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09 PT09PT09PT09PT09PT09PT09PT09Ci0tLSBnY2MvaGFzaC10YWJsZS5oCShy ZXZpc2lvbiAyMTYyMDEpCisrKyBnY2MvaGFzaC10YWJsZS5oCSh3b3JraW5n IGNvcHkpCkBAIC0xOTYsNyArMTk2LDE0IEBAIGFsb25nIHdpdGggR0NDOyBz ZWUgdGhlIGZpbGUgQ09QWUlORzMuCiAjaWZuZGVmIFRZUEVEX0hBU0hUQUJf SAogI2RlZmluZSBUWVBFRF9IQVNIVEFCX0gKIAorI2lmbmRlZiBHRU5FUkFU T1JfRklMRQogI2luY2x1ZGUgImdnYy5oIgorI2Vsc2UKK3RlbXBsYXRlIDx0 eXBlbmFtZSBUPgorVCAqZ2djX2NsZWFyZWRfdmVjX2FsbG9jIChzaXplX3Qp OwordGVtcGxhdGUgPHR5cGVuYW1lIFQ+CitUICpnZ2NfYWxsb2MgKCk7Cisj ZW5kaWYKICNpbmNsdWRlICJoYXNodGFiLmgiCiAjaW5jbHVkZSA8bmV3Pgog Cg== --047d7bea3de680b2c40505712211--