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. From-SVN: r214834
This commit is contained in:
parent
70f0f8b2b1
commit
b086d5308d
17 changed files with 402 additions and 174 deletions
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
14
gcc/dbxout.c
14
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);
|
||||
|
|
|
@ -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. */
|
||||
|
|
55
gcc/except.c
55
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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
21
gcc/ggc.h
21
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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
109
gcc/hash-table.h
109
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 */
|
||||
|
|
62
gcc/symtab.c
62
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;
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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. */
|
||||
|
|
Loading…
Add table
Reference in a new issue