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>
* 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
structure. This is done by marking the pointer with the
@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
@item deletable
......
......@@ -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
root NAME to F. V and LINE are as for write_root.
......@@ -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, "cache") == 0)
;
else
error_at_line (&v->line,
"global `%s' has unknown option `%s'",
......@@ -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",
"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)
return;
......
......@@ -162,6 +162,8 @@ ggc_mark_roots (void)
for (ct = gt_ggc_cache_rtab; *ct; ct++)
ggc_scan_cache_tab (*ct);
gt_clear_caches ();
FOR_EACH_VEC_ELT (extra_cache_vec, i, ctp)
ggc_scan_cache_tab (ctp);
......
......@@ -54,6 +54,9 @@ extern int gt_pch_note_object (void *, void *, gt_note_pointers);
function. */
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. */
typedef void (*gt_pointer_walker) (void *);
......
......@@ -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. */
......@@ -1667,4 +1705,16 @@ gt_pch_nx (hash_table<D> *h, gt_pointer_operator op, void *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 */
......@@ -181,7 +181,7 @@ struct GTY(()) mem_attrs
object in the low part of a 4-byte register, the OFFSET field
will be -3 rather than 0. */
struct GTY(()) reg_attrs {
struct GTY((for_user)) reg_attrs {
tree decl; /* decl corresponding to REG. */
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)))
/* Hash table and temporary node for larger integer const values. */
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 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)))
allocating and freeing up a node repeatably. */
static GTY (()) tree cl_optimization_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. */
......@@ -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 int type_hash_eq (const void *, 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_debug_expr_statistics (void);
static void print_value_expr_statistics (void);
......@@ -585,13 +593,11 @@ init_ttree (void)
value_expr_for_decl = htab_create_ggc (512, tree_decl_map_hash,
tree_decl_map_eq, 0);
int_cst_hash_table = htab_create_ggc (1024, int_cst_hash_hash,
int_cst_hash_eq, NULL);
int_cst_hash_table = hash_table<int_cst_hasher>::create_ggc (1024);
int_cst_node = make_int_cst (1, 1);
cl_option_hash_table = htab_create_ggc (64, cl_option_hash_hash,
cl_option_hash_eq, NULL);
cl_option_hash_table = hash_table<cl_option_hasher>::create_ggc (64);
cl_optimization_node = make_node (OPTIMIZATION_NODE);
cl_target_option_node = make_node (TARGET_OPTION_NODE);
......@@ -1256,10 +1262,10 @@ force_fit_type (tree type, const wide_int_ref &cst,
/* Return the hash code code X, an INTEGER_CST. */
static hashval_t
int_cst_hash_hash (const void *x)
hashval_t
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));
int i;
......@@ -1272,11 +1278,11 @@ int_cst_hash_hash (const void *x)
/* 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. */
static int
int_cst_hash_eq (const void *x, const void *y)
bool
int_cst_hasher::equal (tree x, tree y)
{
const_tree const xt = (const_tree) x;
const_tree const yt = (const_tree) y;
const_tree const xt = x;
const_tree const yt = y;
if (TREE_TYPE (xt) != TREE_TYPE (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)
{
/* Use the cache of larger shared ints, using int_cst_node as
a temporary. */
void **slot;
TREE_INT_CST_ELT (int_cst_node, 0) = hwi;
TREE_TYPE (int_cst_node) = type;
slot = htab_find_slot (int_cst_hash_table, int_cst_node, INSERT);
t = (tree) *slot;
tree *slot = int_cst_hash_table->find_slot (int_cst_node, INSERT);
t = *slot;
if (!t)
{
/* Insert this one into the hash table. */
......@@ -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
for the gc to take care of. There will not be enough of them
to worry about. */
void **slot;
tree nt = build_new_int_cst (type, cst);
slot = htab_find_slot (int_cst_hash_table, nt, INSERT);
t = (tree) *slot;
tree *slot = int_cst_hash_table->find_slot (nt, INSERT);
t = *slot;
if (!t)
{
/* Insert this one into the hash table. */
......@@ -1539,9 +1543,7 @@ cache_integer_cst (tree t)
else
{
/* Use the cache of larger shared ints. */
void **slot;
slot = htab_find_slot (int_cst_hash_table, t, INSERT);
tree *slot = int_cst_hash_table->find_slot (t, INSERT);
/* If there is already an entry for the number verify it's the
same. */
if (*slot)
......@@ -11498,10 +11500,10 @@ tree_nonartificial_location (tree exp)
/* Return the hash code code X, an OPTIMIZATION_NODE or TARGET_OPTION code. */
static hashval_t
cl_option_hash_hash (const void *x)
hashval_t
cl_option_hasher::hash (tree x)
{
const_tree const t = (const_tree) x;
const_tree const t = x;
const char *p;
size_t i;
size_t len = 0;
......@@ -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
same. */
static int
cl_option_hash_eq (const void *x, const void *y)
bool
cl_option_hasher::equal (tree x, tree y)
{
const_tree const xt = (const_tree) x;
const_tree const yt = (const_tree) y;
const_tree const xt = x;
const_tree const yt = y;
const char *xp;
const char *yp;
size_t len;
......@@ -11569,15 +11571,14 @@ tree
build_optimization_node (struct gcc_options *opts)
{
tree t;
void **slot;
/* Use the cache of optimization nodes. */
cl_optimization_save (TREE_OPTIMIZATION (cl_optimization_node),
opts);
slot = htab_find_slot (cl_option_hash_table, cl_optimization_node, INSERT);
t = (tree) *slot;
tree *slot = cl_option_hash_table->find_slot (cl_optimization_node, INSERT);
t = *slot;
if (!t)
{
/* Insert this one into the hash table. */
......@@ -11597,15 +11598,14 @@ tree
build_target_option_node (struct gcc_options *opts)
{
tree t;
void **slot;
/* Use the cache of optimization nodes. */
cl_target_option_save (TREE_TARGET_OPTION (cl_target_option_node),
opts);
slot = htab_find_slot (cl_option_hash_table, cl_target_option_node, INSERT);
t = (tree) *slot;
tree *slot = cl_option_hash_table->find_slot (cl_target_option_node, INSERT);
t = *slot;
if (!t)
{
/* Insert this one into the hash table. */
......@@ -11619,26 +11619,16 @@ build_target_option_node (struct gcc_options *opts)
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,
so that they aren't saved during PCH writing. */
void
prepare_target_option_nodes_for_pch (void)
{
htab_traverse (cl_option_hash_table, prepare_target_option_node_for_pch,
NULL);
hash_table<cl_option_hasher>::iterator iter = cl_option_hash_table->begin ();
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
......
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