diff options
author | tbsaunde <tbsaunde@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-09-02 22:46:00 +0000 |
---|---|---|
committer | tbsaunde <tbsaunde@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-09-02 22:46:00 +0000 |
commit | 8f359205089fa4570dd9db058aed35e391ceb357 (patch) | |
tree | cb4aa8d407cf40f28ef0fcd771f1109d53f44f3c /gcc | |
parent | c4de79b608465ea31bd920224bd7fdff2deeaecf (diff) | |
download | gcc-8f359205089fa4570dd9db058aed35e391ceb357.tar.gz |
support ggc hash_map and hash_set
gcc/ChangeLog:
* alloc-pool.c: Include coretypes.h.
* cgraph.h, dbxout.c, dwarf2out.c, except.c, except.h, function.c,
function.h, symtab.c, tree-cfg.c, tree-eh.c: Use hash_map and
hash_set instead of htab.
* ggc-page.c (in_gc): New variable.
(ggc_free): Do nothing if a collection is taking place.
(ggc_collect): Set in_gc appropriately.
* ggc.h (gt_ggc_mx(const char *)): New function.
(gt_pch_nx(const char *)): Likewise.
(gt_ggc_mx(int)): Likewise.
(gt_pch_nx(int)): Likewise.
* hash-map.h (hash_map::hash_entry::ggc_mx): Likewise.
(hash_map::hash_entry::pch_nx): Likewise.
(hash_map::hash_entry::pch_nx_helper): Likewise.
(hash_map::hash_map): Adjust.
(hash_map::create_ggc): New function.
(gt_ggc_mx): Likewise.
(gt_pch_nx): Likewise.
* hash-set.h (default_hashset_traits::ggc_mx): Likewise.
(default_hashset_traits::pch_nx): Likewise.
(hash_set::hash_entry::ggc_mx): Likewise.
(hash_set::hash_entry::pch_nx): Likewise.
(hash_set::hash_entry::pch_nx_helper): Likewise.
(hash_set::hash_set): Adjust.
(hash_set::create_ggc): New function.
(hash_set::elements): Likewise.
(gt_ggc_mx): Likewise.
(gt_pch_nx): Likewise.
* hash-table.h (hash_table::hash_table): Adjust.
(hash_table::m_ggc): New member.
(hash_table::~hash_table): Adjust.
(hash_table::expand): Likewise.
(hash_table::empty): Likewise.
(gt_ggc_mx): New function.
(hashtab_entry_note_pointers): Likewise.
(gt_pch_nx): Likewise.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@214834 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 39 | ||||
-rw-r--r-- | gcc/alloc-pool.c | 1 | ||||
-rw-r--r-- | gcc/cgraph.h | 3 | ||||
-rw-r--r-- | gcc/dbxout.c | 14 | ||||
-rw-r--r-- | gcc/dwarf2out.c | 10 | ||||
-rw-r--r-- | gcc/except.c | 55 | ||||
-rw-r--r-- | gcc/except.h | 6 | ||||
-rw-r--r-- | gcc/function.c | 10 | ||||
-rw-r--r-- | gcc/function.h | 3 | ||||
-rw-r--r-- | gcc/ggc-page.c | 10 | ||||
-rw-r--r-- | gcc/ggc.h | 21 | ||||
-rw-r--r-- | gcc/hash-map.h | 79 | ||||
-rw-r--r-- | gcc/hash-set.h | 94 | ||||
-rw-r--r-- | gcc/hash-table.h | 109 | ||||
-rw-r--r-- | gcc/symtab.c | 62 | ||||
-rw-r--r-- | gcc/tree-cfg.c | 22 | ||||
-rw-r--r-- | gcc/tree-eh.c | 38 |
17 files changed, 402 insertions, 174 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b60054b18f6..22e69c0e7db 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,42 @@ +2014-09-02 Trevor Saunders <tsaunders@mozilla.com> + + * alloc-pool.c: Include coretypes.h. + * cgraph.h, dbxout.c, dwarf2out.c, except.c, except.h, function.c, + function.h, symtab.c, tree-cfg.c, tree-eh.c: Use hash_map and + hash_set instead of htab. + * ggc-page.c (in_gc): New variable. + (ggc_free): Do nothing if a collection is taking place. + (ggc_collect): Set in_gc appropriately. + * ggc.h (gt_ggc_mx(const char *)): New function. + (gt_pch_nx(const char *)): Likewise. + (gt_ggc_mx(int)): Likewise. + (gt_pch_nx(int)): Likewise. + * hash-map.h (hash_map::hash_entry::ggc_mx): Likewise. + (hash_map::hash_entry::pch_nx): Likewise. + (hash_map::hash_entry::pch_nx_helper): Likewise. +(hash_map::hash_map): Adjust. +(hash_map::create_ggc): New function. +(gt_ggc_mx): Likewise. +(gt_pch_nx): Likewise. + * hash-set.h (default_hashset_traits::ggc_mx): Likewise. +(default_hashset_traits::pch_nx): Likewise. +(hash_set::hash_entry::ggc_mx): Likewise. +(hash_set::hash_entry::pch_nx): Likewise. +(hash_set::hash_entry::pch_nx_helper): Likewise. +(hash_set::hash_set): Adjust. +(hash_set::create_ggc): New function. +(hash_set::elements): Likewise. +(gt_ggc_mx): Likewise. +(gt_pch_nx): Likewise. + * hash-table.h (hash_table::hash_table): Adjust. +(hash_table::m_ggc): New member. + (hash_table::~hash_table): Adjust. + (hash_table::expand): Likewise. + (hash_table::empty): Likewise. +(gt_ggc_mx): New function. + (hashtab_entry_note_pointers): Likewise. +(gt_pch_nx): Likewise. + 2014-09-02 Bill Schmidt <wschmidt@linux.vnet.ibm.com> * config/rs6000/rs6000-builtin.def (XVCVSXDDP_SCALE): New diff --git a/gcc/alloc-pool.c b/gcc/alloc-pool.c index 0d318351474..bfaa0e4662f 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 879899c7d36..030a1c771b7 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 946f1d15e90..d856bddc115 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 7c0be8686ef..21afc3fe21e 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 1f57c3f5cd8..fecc06046a2 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 71a8dceba8a..32591513204 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 464c6cdaa57..2e46799f751 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 071f5dd237c..e71210df350 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 393954089f8..2a9b2d9e7fa 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 1c0fd3d1ba5..6280c433809 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 d2eed337ad4..c65e1e57999 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 47bae9ed77d..0a500cb441a 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 9c6a34ad70b..c2a68fd23a2 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_checking_assert (map->m_entries == obj); + for (size_t i = 0; i < map->m_size; i++) + { + typedef hash_table<D> table; + if (table::is_empty (map->m_entries[i]) + || table::is_deleted (map->m_entries[i])) + continue; + + D::pch_nx (map->m_entries[i], op, cookie); + } +} + +template<typename D> +static void +gt_pch_nx (hash_table<D> *h) +{ + gcc_checking_assert (gt_pch_note_object (h->m_entries, h, + hashtab_entry_note_pointers<D>)); + for (size_t i = 0; i < h->m_size; i++) + { + if (hash_table<D>::is_empty (h->m_entries[i]) + || hash_table<D>::is_deleted (h->m_entries[i])) + continue; + + D::pch_nx (h->m_entries[i]); + } +} + #endif /* TYPED_HASHTAB_H */ diff --git a/gcc/symtab.c b/gcc/symtab.c index 739a8e4a308..792b3b50ea6 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 c75516db112..e89d76a015a 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 6c6faf30364..9da8da28b36 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. */ |