Commit aebf76a2 by Trevor Saunders Committed by Trevor Saunders

implement a replacement for if_marked

gcc/ChangeLog:

2014-11-20  Trevor Saunders  <tsaunders@mozilla.com>

	* doc/gty.texi: Document the new cache gty attribute.
	* gengtype.c (finish_cache_funcs): New function.
	(write_roots): Call gt_clear_cache on global variables with the cache
	gty attribute.
	* ggc-common.c (ggc_mark_roots): Call gt_clear_caches.
	* ggc.h (gt_clear_caches): New declaration.
	* hash-table.h (struct ggc_cache_hasher): New hasher for caches in gc
	memory.
	(gt_cleare_cache): New function.
	* emit-rtl.c, rtl.h, tree.c: Use hash_table instead of htab.

From-SVN: r217866
parent 77486f44
2014-11-20 Trevor Saunders <tsaunders@mozilla.com>
* doc/gty.texi: Document the new cache gty attribute.
* gengtype.c (finish_cache_funcs): New function.
(write_roots): Call gt_clear_cache on global variables with the cache
gty attribute.
* ggc-common.c (ggc_mark_roots): Call gt_clear_caches.
* ggc.h (gt_clear_caches): New declaration.
* hash-table.h (struct ggc_cache_hasher): New hasher for caches in gc
memory.
(gt_cleare_cache): New function.
* emit-rtl.c, rtl.h, tree.c: Use hash_table instead of htab.
2014-11-20 Segher Boessenkool <segher@kernel.crashing.org> 2014-11-20 Segher Boessenkool <segher@kernel.crashing.org>
* combine.c (try_combine): Prefer to delete dead SETs inside * combine.c (try_combine): Prefer to delete dead SETs inside
...@@ -293,6 +293,14 @@ the pointed-to structure should use the same parameters as the outer ...@@ -293,6 +293,14 @@ the pointed-to structure should use the same parameters as the outer
structure. This is done by marking the pointer with the structure. This is done by marking the pointer with the
@code{use_params} option. @code{use_params} option.
@findex cache
@item cache
When the @code{cache} option is applied to a global variable gt_clear_cache is
called on that variable between the mark and sweep phases of garbage
collection. The gt_clear_cache function is free to mark blocks as used, or to
clear pointers in the variable.
@findex deletable @findex deletable
@item deletable @item deletable
......
...@@ -4482,6 +4482,60 @@ finish_root_table (struct flist *flp, const char *pfx, const char *lastname, ...@@ -4482,6 +4482,60 @@ finish_root_table (struct flist *flp, const char *pfx, const char *lastname,
} }
} }
/* Finish off the created gt_clear_caches_file_c functions. */
static void
finish_cache_funcs (flist *flp)
{
struct flist *fli2;
for (fli2 = flp; fli2; fli2 = fli2->next)
if (fli2->started_p)
{
oprintf (fli2->f, "}\n\n");
}
for (fli2 = flp; fli2 && base_files; fli2 = fli2->next)
if (fli2->started_p)
{
lang_bitmap bitmap = get_lang_bitmap (fli2->file);
int fnum;
for (fnum = 0; bitmap != 0; fnum++, bitmap >>= 1)
if (bitmap & 1)
{
oprintf (base_files[fnum], "extern void gt_clear_caches_");
put_mangled_filename (base_files[fnum], fli2->file);
oprintf (base_files[fnum], " ();\n");
}
}
for (size_t fnum = 0; base_files && fnum < num_lang_dirs; fnum++)
oprintf (base_files[fnum], "void\ngt_clear_caches ()\n{\n");
for (fli2 = flp; fli2; fli2 = fli2->next)
if (fli2->started_p)
{
lang_bitmap bitmap = get_lang_bitmap (fli2->file);
int fnum;
fli2->started_p = 0;
for (fnum = 0; base_files && bitmap != 0; fnum++, bitmap >>= 1)
if (bitmap & 1)
{
oprintf (base_files[fnum], " gt_clear_caches_");
put_mangled_filename (base_files[fnum], fli2->file);
oprintf (base_files[fnum], " ();\n");
}
}
for (size_t fnum = 0; base_files && fnum < num_lang_dirs; fnum++)
{
oprintf (base_files[fnum], "}\n");
}
}
/* Write the first three fields (pointer, count and stride) for /* Write the first three fields (pointer, count and stride) for
root NAME to F. V and LINE are as for write_root. root NAME to F. V and LINE are as for write_root.
...@@ -4801,6 +4855,8 @@ write_roots (pair_p variables, bool emit_pch) ...@@ -4801,6 +4855,8 @@ write_roots (pair_p variables, bool emit_pch)
; ;
else if (strcmp (o->name, "if_marked") == 0) else if (strcmp (o->name, "if_marked") == 0)
; ;
else if (strcmp (o->name, "cache") == 0)
;
else else
error_at_line (&v->line, error_at_line (&v->line,
"global `%s' has unknown option `%s'", "global `%s' has unknown option `%s'",
...@@ -4952,6 +5008,37 @@ write_roots (pair_p variables, bool emit_pch) ...@@ -4952,6 +5008,37 @@ write_roots (pair_p variables, bool emit_pch)
finish_root_table (flp, "ggc_rc", "LAST_GGC_CACHE_TAB", "ggc_cache_tab", finish_root_table (flp, "ggc_rc", "LAST_GGC_CACHE_TAB", "ggc_cache_tab",
"gt_ggc_cache_rtab"); "gt_ggc_cache_rtab");
for (v = variables; v; v = v->next)
{
outf_p f = get_output_file_with_visibility (CONST_CAST (input_file*,
v->line.file));
struct flist *fli;
bool cache = false;
options_p o;
for (o = v->opt; o; o = o->next)
if (strcmp (o->name, "cache") == 0)
cache = true;
if (!cache)
continue;
for (fli = flp; fli; fli = fli->next)
if (fli->f == f)
break;
if (!fli->started_p)
{
fli->started_p = 1;
oprintf (f, "void\ngt_clear_caches_");
put_mangled_filename (f, v->line.file);
oprintf (f, " ()\n{\n");
}
oprintf (f, " gt_cleare_cache (%s);\n", v->name);
}
finish_cache_funcs (flp);
if (!emit_pch) if (!emit_pch)
return; return;
......
...@@ -162,6 +162,8 @@ ggc_mark_roots (void) ...@@ -162,6 +162,8 @@ ggc_mark_roots (void)
for (ct = gt_ggc_cache_rtab; *ct; ct++) for (ct = gt_ggc_cache_rtab; *ct; ct++)
ggc_scan_cache_tab (*ct); ggc_scan_cache_tab (*ct);
gt_clear_caches ();
FOR_EACH_VEC_ELT (extra_cache_vec, i, ctp) FOR_EACH_VEC_ELT (extra_cache_vec, i, ctp)
ggc_scan_cache_tab (ctp); ggc_scan_cache_tab (ctp);
......
...@@ -54,6 +54,9 @@ extern int gt_pch_note_object (void *, void *, gt_note_pointers); ...@@ -54,6 +54,9 @@ extern int gt_pch_note_object (void *, void *, gt_note_pointers);
function. */ function. */
extern void gt_pch_note_reorder (void *, void *, gt_handle_reorder); extern void gt_pch_note_reorder (void *, void *, gt_handle_reorder);
/* generated function to clear caches in gc memory. */
extern void gt_clear_caches ();
/* Mark the object in the first parameter and anything it points to. */ /* Mark the object in the first parameter and anything it points to. */
typedef void (*gt_pointer_walker) (void *); typedef void (*gt_pointer_walker) (void *);
......
...@@ -334,6 +334,44 @@ struct ggc_hasher ...@@ -334,6 +334,44 @@ struct ggc_hasher
} }
}; };
/* Hasher for cache entry in gc memory. */
template<typename T>
struct ggc_cache_hasher
{
typedef T value_type;
typedef T compare_type;
typedef int store_values_directly;
static void remove (T &) {}
/* Entries are weakly held because this is for caches. */
static void ggc_mx (T &) {}
static void
pch_nx (T &p)
{
extern void gt_pch_nx (T &);
gt_pch_nx (p);
}
static void
pch_nx (T &p, gt_pointer_operator op, void *cookie)
{
op (&p, cookie);
}
/* Clear out entries if they are about to be gc'd. */
static void
handle_cache_entry (T &e)
{
if (e != HTAB_EMPTY_ENTRY && e != HTAB_DELETED_ENTRY && !ggc_marked_p (e))
e = static_cast<T> (HTAB_DELETED_ENTRY);
}
};
/* Table of primes and their inversion information. */ /* Table of primes and their inversion information. */
...@@ -1667,4 +1705,16 @@ gt_pch_nx (hash_table<D> *h, gt_pointer_operator op, void *cookie) ...@@ -1667,4 +1705,16 @@ gt_pch_nx (hash_table<D> *h, gt_pointer_operator op, void *cookie)
op (&h->m_entries, cookie); op (&h->m_entries, cookie);
} }
template<typename H>
inline void
gt_cleare_cache (hash_table<H> *h)
{
if (!h)
return;
for (typename hash_table<H>::iterator iter = h->begin (); iter != h->end ();
++iter)
H::handle_cache_entry (*iter);
}
#endif /* TYPED_HASHTAB_H */ #endif /* TYPED_HASHTAB_H */
...@@ -181,7 +181,7 @@ struct GTY(()) mem_attrs ...@@ -181,7 +181,7 @@ struct GTY(()) mem_attrs
object in the low part of a 4-byte register, the OFFSET field object in the low part of a 4-byte register, the OFFSET field
will be -3 rather than 0. */ will be -3 rather than 0. */
struct GTY(()) reg_attrs { struct GTY((for_user)) reg_attrs {
tree decl; /* decl corresponding to REG. */ tree decl; /* decl corresponding to REG. */
HOST_WIDE_INT offset; /* Offset from start of DECL. */ HOST_WIDE_INT offset; /* Offset from start of DECL. */
}; };
......
...@@ -205,8 +205,14 @@ static GTY ((if_marked ("type_hash_marked_p"), param_is (struct type_hash))) ...@@ -205,8 +205,14 @@ static GTY ((if_marked ("type_hash_marked_p"), param_is (struct type_hash)))
/* Hash table and temporary node for larger integer const values. */ /* Hash table and temporary node for larger integer const values. */
static GTY (()) tree int_cst_node; static GTY (()) tree int_cst_node;
static GTY ((if_marked ("ggc_marked_p"), param_is (union tree_node)))
htab_t int_cst_hash_table; struct int_cst_hasher : ggc_cache_hasher<tree>
{
static hashval_t hash (tree t);
static bool equal (tree x, tree y);
};
static GTY ((cache)) hash_table<int_cst_hasher> *int_cst_hash_table;
/* Hash table for optimization flags and target option flags. Use the same /* Hash table for optimization flags and target option flags. Use the same
hash table for both sets of options. Nodes for building the current hash table for both sets of options. Nodes for building the current
...@@ -215,8 +221,14 @@ static GTY ((if_marked ("ggc_marked_p"), param_is (union tree_node))) ...@@ -215,8 +221,14 @@ static GTY ((if_marked ("ggc_marked_p"), param_is (union tree_node)))
allocating and freeing up a node repeatably. */ allocating and freeing up a node repeatably. */
static GTY (()) tree cl_optimization_node; static GTY (()) tree cl_optimization_node;
static GTY (()) tree cl_target_option_node; static GTY (()) tree cl_target_option_node;
static GTY ((if_marked ("ggc_marked_p"), param_is (union tree_node)))
htab_t cl_option_hash_table; struct cl_option_hasher : ggc_cache_hasher<tree>
{
static hashval_t hash (tree t);
static bool equal (tree x, tree y);
};
static GTY ((cache)) hash_table<cl_option_hasher> *cl_option_hash_table;
/* General tree->tree mapping structure for use in hash tables. */ /* General tree->tree mapping structure for use in hash tables. */
...@@ -233,10 +245,6 @@ static GTY ((if_marked ("tree_vec_map_marked_p"), param_is (struct tree_vec_map) ...@@ -233,10 +245,6 @@ static GTY ((if_marked ("tree_vec_map_marked_p"), param_is (struct tree_vec_map)
static void set_type_quals (tree, int); static void set_type_quals (tree, int);
static int type_hash_eq (const void *, const void *); static int type_hash_eq (const void *, const void *);
static hashval_t type_hash_hash (const void *); static hashval_t type_hash_hash (const void *);
static hashval_t int_cst_hash_hash (const void *);
static int int_cst_hash_eq (const void *, const void *);
static hashval_t cl_option_hash_hash (const void *);
static int cl_option_hash_eq (const void *, const void *);
static void print_type_hash_statistics (void); static void print_type_hash_statistics (void);
static void print_debug_expr_statistics (void); static void print_debug_expr_statistics (void);
static void print_value_expr_statistics (void); static void print_value_expr_statistics (void);
...@@ -585,13 +593,11 @@ init_ttree (void) ...@@ -585,13 +593,11 @@ init_ttree (void)
value_expr_for_decl = htab_create_ggc (512, tree_decl_map_hash, value_expr_for_decl = htab_create_ggc (512, tree_decl_map_hash,
tree_decl_map_eq, 0); tree_decl_map_eq, 0);
int_cst_hash_table = htab_create_ggc (1024, int_cst_hash_hash, int_cst_hash_table = hash_table<int_cst_hasher>::create_ggc (1024);
int_cst_hash_eq, NULL);
int_cst_node = make_int_cst (1, 1); int_cst_node = make_int_cst (1, 1);
cl_option_hash_table = htab_create_ggc (64, cl_option_hash_hash, cl_option_hash_table = hash_table<cl_option_hasher>::create_ggc (64);
cl_option_hash_eq, NULL);
cl_optimization_node = make_node (OPTIMIZATION_NODE); cl_optimization_node = make_node (OPTIMIZATION_NODE);
cl_target_option_node = make_node (TARGET_OPTION_NODE); cl_target_option_node = make_node (TARGET_OPTION_NODE);
...@@ -1256,10 +1262,10 @@ force_fit_type (tree type, const wide_int_ref &cst, ...@@ -1256,10 +1262,10 @@ force_fit_type (tree type, const wide_int_ref &cst,
/* Return the hash code code X, an INTEGER_CST. */ /* Return the hash code code X, an INTEGER_CST. */
static hashval_t hashval_t
int_cst_hash_hash (const void *x) int_cst_hasher::hash (tree x)
{ {
const_tree const t = (const_tree) x; const_tree const t = x;
hashval_t code = htab_hash_pointer (TREE_TYPE (t)); hashval_t code = htab_hash_pointer (TREE_TYPE (t));
int i; int i;
...@@ -1272,11 +1278,11 @@ int_cst_hash_hash (const void *x) ...@@ -1272,11 +1278,11 @@ int_cst_hash_hash (const void *x)
/* Return nonzero if the value represented by *X (an INTEGER_CST tree node) /* Return nonzero if the value represented by *X (an INTEGER_CST tree node)
is the same as that given by *Y, which is the same. */ is the same as that given by *Y, which is the same. */
static int bool
int_cst_hash_eq (const void *x, const void *y) int_cst_hasher::equal (tree x, tree y)
{ {
const_tree const xt = (const_tree) x; const_tree const xt = x;
const_tree const yt = (const_tree) y; const_tree const yt = y;
if (TREE_TYPE (xt) != TREE_TYPE (yt) if (TREE_TYPE (xt) != TREE_TYPE (yt)
|| TREE_INT_CST_NUNITS (xt) != TREE_INT_CST_NUNITS (yt) || TREE_INT_CST_NUNITS (xt) != TREE_INT_CST_NUNITS (yt)
...@@ -1408,13 +1414,12 @@ wide_int_to_tree (tree type, const wide_int_ref &pcst) ...@@ -1408,13 +1414,12 @@ wide_int_to_tree (tree type, const wide_int_ref &pcst)
{ {
/* Use the cache of larger shared ints, using int_cst_node as /* Use the cache of larger shared ints, using int_cst_node as
a temporary. */ a temporary. */
void **slot;
TREE_INT_CST_ELT (int_cst_node, 0) = hwi; TREE_INT_CST_ELT (int_cst_node, 0) = hwi;
TREE_TYPE (int_cst_node) = type; TREE_TYPE (int_cst_node) = type;
slot = htab_find_slot (int_cst_hash_table, int_cst_node, INSERT); tree *slot = int_cst_hash_table->find_slot (int_cst_node, INSERT);
t = (tree) *slot; t = *slot;
if (!t) if (!t)
{ {
/* Insert this one into the hash table. */ /* Insert this one into the hash table. */
...@@ -1430,11 +1435,10 @@ wide_int_to_tree (tree type, const wide_int_ref &pcst) ...@@ -1430,11 +1435,10 @@ wide_int_to_tree (tree type, const wide_int_ref &pcst)
/* The value either hashes properly or we drop it on the floor /* The value either hashes properly or we drop it on the floor
for the gc to take care of. There will not be enough of them for the gc to take care of. There will not be enough of them
to worry about. */ to worry about. */
void **slot;
tree nt = build_new_int_cst (type, cst); tree nt = build_new_int_cst (type, cst);
slot = htab_find_slot (int_cst_hash_table, nt, INSERT); tree *slot = int_cst_hash_table->find_slot (nt, INSERT);
t = (tree) *slot; t = *slot;
if (!t) if (!t)
{ {
/* Insert this one into the hash table. */ /* Insert this one into the hash table. */
...@@ -1539,9 +1543,7 @@ cache_integer_cst (tree t) ...@@ -1539,9 +1543,7 @@ cache_integer_cst (tree t)
else else
{ {
/* Use the cache of larger shared ints. */ /* Use the cache of larger shared ints. */
void **slot; tree *slot = int_cst_hash_table->find_slot (t, INSERT);
slot = htab_find_slot (int_cst_hash_table, t, INSERT);
/* If there is already an entry for the number verify it's the /* If there is already an entry for the number verify it's the
same. */ same. */
if (*slot) if (*slot)
...@@ -11498,10 +11500,10 @@ tree_nonartificial_location (tree exp) ...@@ -11498,10 +11500,10 @@ tree_nonartificial_location (tree exp)
/* Return the hash code code X, an OPTIMIZATION_NODE or TARGET_OPTION code. */ /* Return the hash code code X, an OPTIMIZATION_NODE or TARGET_OPTION code. */
static hashval_t hashval_t
cl_option_hash_hash (const void *x) cl_option_hasher::hash (tree x)
{ {
const_tree const t = (const_tree) x; const_tree const t = x;
const char *p; const char *p;
size_t i; size_t i;
size_t len = 0; size_t len = 0;
...@@ -11532,11 +11534,11 @@ cl_option_hash_hash (const void *x) ...@@ -11532,11 +11534,11 @@ cl_option_hash_hash (const void *x)
TARGET_OPTION tree node) is the same as that given by *Y, which is the TARGET_OPTION tree node) is the same as that given by *Y, which is the
same. */ same. */
static int bool
cl_option_hash_eq (const void *x, const void *y) cl_option_hasher::equal (tree x, tree y)
{ {
const_tree const xt = (const_tree) x; const_tree const xt = x;
const_tree const yt = (const_tree) y; const_tree const yt = y;
const char *xp; const char *xp;
const char *yp; const char *yp;
size_t len; size_t len;
...@@ -11569,15 +11571,14 @@ tree ...@@ -11569,15 +11571,14 @@ tree
build_optimization_node (struct gcc_options *opts) build_optimization_node (struct gcc_options *opts)
{ {
tree t; tree t;
void **slot;
/* Use the cache of optimization nodes. */ /* Use the cache of optimization nodes. */
cl_optimization_save (TREE_OPTIMIZATION (cl_optimization_node), cl_optimization_save (TREE_OPTIMIZATION (cl_optimization_node),
opts); opts);
slot = htab_find_slot (cl_option_hash_table, cl_optimization_node, INSERT); tree *slot = cl_option_hash_table->find_slot (cl_optimization_node, INSERT);
t = (tree) *slot; t = *slot;
if (!t) if (!t)
{ {
/* Insert this one into the hash table. */ /* Insert this one into the hash table. */
...@@ -11597,15 +11598,14 @@ tree ...@@ -11597,15 +11598,14 @@ tree
build_target_option_node (struct gcc_options *opts) build_target_option_node (struct gcc_options *opts)
{ {
tree t; tree t;
void **slot;
/* Use the cache of optimization nodes. */ /* Use the cache of optimization nodes. */
cl_target_option_save (TREE_TARGET_OPTION (cl_target_option_node), cl_target_option_save (TREE_TARGET_OPTION (cl_target_option_node),
opts); opts);
slot = htab_find_slot (cl_option_hash_table, cl_target_option_node, INSERT); tree *slot = cl_option_hash_table->find_slot (cl_target_option_node, INSERT);
t = (tree) *slot; t = *slot;
if (!t) if (!t)
{ {
/* Insert this one into the hash table. */ /* Insert this one into the hash table. */
...@@ -11619,26 +11619,16 @@ build_target_option_node (struct gcc_options *opts) ...@@ -11619,26 +11619,16 @@ build_target_option_node (struct gcc_options *opts)
return t; return t;
} }
/* Reset TREE_TARGET_GLOBALS cache for TARGET_OPTION_NODE.
Called through htab_traverse. */
static int
prepare_target_option_node_for_pch (void **slot, void *)
{
tree node = (tree) *slot;
if (TREE_CODE (node) == TARGET_OPTION_NODE)
TREE_TARGET_GLOBALS (node) = NULL;
return 1;
}
/* Clear TREE_TARGET_GLOBALS of all TARGET_OPTION_NODE trees, /* Clear TREE_TARGET_GLOBALS of all TARGET_OPTION_NODE trees,
so that they aren't saved during PCH writing. */ so that they aren't saved during PCH writing. */
void void
prepare_target_option_nodes_for_pch (void) prepare_target_option_nodes_for_pch (void)
{ {
htab_traverse (cl_option_hash_table, prepare_target_option_node_for_pch, hash_table<cl_option_hasher>::iterator iter = cl_option_hash_table->begin ();
NULL); for (; iter != cl_option_hash_table->end (); ++iter)
if (TREE_CODE (*iter) == TARGET_OPTION_NODE)
TREE_TARGET_GLOBALS (*iter) = NULL;
} }
/* Determine the "ultimate origin" of a block. The block may be an inlined /* Determine the "ultimate origin" of a block. The block may be an inlined
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment