fold-const.c (hashtab.h): Include.

* fold-const.c (hashtab.h): Include.
	(int_const_binop): Remove FORSIZE arg and compute from type; all
	callers changed.
	Call size_int_type_wide for all single-word constants.
	(size_htab_hash, size_htab_eq): New functions.
	(size_int_type_wide): Rework to use hash table.
	* ggc-common.c (hashtab.h): Include.
	(struct d_htab_root): New struct.
	(d_htab_roots): New variable.
	(ggc_add_deletable_htab, ggc_htab_delete): New functions
	(ggc_mark_roots): Handle deletable htabs.
	* ggc-page.c (ggc_marked_p): New function.
	* ggc-simple.c (ggc_marked_p): Likewise.
	* ggc.h: Reformatting throughout.
	(ggc_marked_p, ggc_add_deletable_htab): New declarations.
	* tree.c (init_obstacks): Make type_hash_table a deletable root.
	(type_hash_add): Allocate struct type_hash from GC memory.
	(mark_hash_entry, mark_type_hash): Deleted.
	(type_hash_marked_p, type_hash_mark): New functions.
	* Makefile.in (ggc-common.o, fold-const.o): Include hashtab.h.

From-SVN: r45710
This commit is contained in:
Richard Kenner 2001-09-20 15:12:54 +00:00 committed by Richard Kenner
parent c762ab6ebb
commit 4c160717ca
8 changed files with 314 additions and 107 deletions

View File

@ -1,3 +1,26 @@
Thu Sep 20 09:00:27 2001 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* fold-const.c (hashtab.h): Include.
(int_const_binop): Remove FORSIZE arg and compute from type; all
callers changed.
Call size_int_type_wide for all single-word constants.
(size_htab_hash, size_htab_eq): New functions.
(size_int_type_wide): Rework to use hash table.
* ggc-common.c (hashtab.h): Include.
(struct d_htab_root): New struct.
(d_htab_roots): New variable.
(ggc_add_deletable_htab, ggc_htab_delete): New functions
(ggc_mark_roots): Handle deletable htabs.
* ggc-page.c (ggc_marked_p): New function.
* ggc-simple.c (ggc_marked_p): Likewise.
* ggc.h: Reformatting throughout.
(ggc_marked_p, ggc_add_deletable_htab): New declarations.
* tree.c (init_obstacks): Make type_hash_table a deletable root.
(type_hash_add): Allocate struct type_hash from GC memory.
(mark_hash_entry, mark_type_hash): Deleted.
(type_hash_marked_p, type_hash_mark): New functions.
* Makefile.in (ggc-common.o, fold-const.o): Include hashtab.h.
Thu Sep 20 12:49:34 2001 J"orn Rennecke <amylaar@redhat.com>
* sh.c (shiftcosts): Don't use shiftcosts array for modes wider

View File

@ -1310,7 +1310,7 @@ dumpvers: dumpvers.c
version.o: version.c version.h
ggc-common.o: ggc-common.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) \
flags.h $(GGC_H) varray.h hash.h $(TM_P_H)
flags.h $(GGC_H) varray.h hash.h $(HASHTAB_H) $(TM_P_H)
ggc-simple.o: ggc-simple.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
$(GGC_H) varray.h $(TIMEVAR_H) $(TM_P_H)
@ -1346,8 +1346,8 @@ tree.o : tree.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) flags.h function.h toplev.h \
print-tree.o : print-tree.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(GGC_H)
stor-layout.o : stor-layout.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) flags.h \
function.h $(EXPR_H) $(RTL_H) toplev.h $(GGC_H) $(TM_P_H)
fold-const.o : fold-const.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) flags.h toplev.h \
$(EXPR_H) $(RTL_H) $(GGC_H) $(TM_P_H)
fold-const.o : fold-const.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) flags.h \
toplev.h $(HASHTAB_H) $(EXPR_H) $(RTL_H) $(GGC_H) $(TM_P_H)
diagnostic.o : diagnostic.c diagnostic.h real.h diagnostic.def \
$(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(TM_P_H) flags.h $(GGC_H) \
input.h toplev.h intl.h

View File

@ -51,6 +51,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "tm_p.h"
#include "toplev.h"
#include "ggc.h"
#include "hashtab.h"
static void encode PARAMS ((HOST_WIDE_INT *,
unsigned HOST_WIDE_INT,
@ -65,9 +66,11 @@ static tree negate_expr PARAMS ((tree));
static tree split_tree PARAMS ((tree, enum tree_code, tree *, tree *,
int));
static tree associate_trees PARAMS ((tree, tree, enum tree_code, tree));
static tree int_const_binop PARAMS ((enum tree_code, tree, tree, int, int));
static tree int_const_binop PARAMS ((enum tree_code, tree, tree, int));
static void const_binop_1 PARAMS ((PTR));
static tree const_binop PARAMS ((enum tree_code, tree, tree, int));
static hashval_t size_htab_hash PARAMS ((const void *));
static int size_htab_eq PARAMS ((const void *, const void *));
static void fold_convert_1 PARAMS ((PTR));
static tree fold_convert PARAMS ((tree, tree));
static enum tree_code invert_tree_comparison PARAMS ((enum tree_code));
@ -1478,14 +1481,13 @@ associate_trees (t1, t2, code, type)
/* Combine two integer constants ARG1 and ARG2 under operation CODE
to produce a new constant.
If NOTRUNC is nonzero, do not truncate the result to fit the data type.
If FORSIZE is nonzero, compute overflow for unsigned types. */
If NOTRUNC is nonzero, do not truncate the result to fit the data type. */
static tree
int_const_binop (code, arg1, arg2, notrunc, forsize)
int_const_binop (code, arg1, arg2, notrunc)
enum tree_code code;
register tree arg1, arg2;
int notrunc, forsize;
int notrunc;
{
unsigned HOST_WIDE_INT int1l, int2l;
HOST_WIDE_INT int1h, int2h;
@ -1494,7 +1496,10 @@ int_const_binop (code, arg1, arg2, notrunc, forsize)
unsigned HOST_WIDE_INT garbagel;
HOST_WIDE_INT garbageh;
register tree t;
int uns = TREE_UNSIGNED (TREE_TYPE (arg1));
tree type = TREE_TYPE (arg1);
int uns = TREE_UNSIGNED (type);
int is_sizetype
= (TREE_CODE (type) == INTEGER_TYPE && TYPE_IS_SIZETYPE (type));
int overflow = 0;
int no_overflow = 0;
@ -1527,7 +1532,7 @@ int_const_binop (code, arg1, arg2, notrunc, forsize)
/* It's unclear from the C standard whether shifts can overflow.
The following code ignores overflow; perhaps a C standard
interpretation ruling is needed. */
lshift_double (int1l, int1h, int2l, TYPE_PRECISION (TREE_TYPE (arg1)),
lshift_double (int1l, int1h, int2l, TYPE_PRECISION (type),
&low, &hi, !uns);
no_overflow = 1;
break;
@ -1535,7 +1540,7 @@ int_const_binop (code, arg1, arg2, notrunc, forsize)
case RROTATE_EXPR:
int2l = - int2l;
case LROTATE_EXPR:
lrotate_double (int1l, int1h, int2l, TYPE_PRECISION (TREE_TYPE (arg1)),
lrotate_double (int1l, int1h, int2l, TYPE_PRECISION (type),
&low, &hi);
break;
@ -1583,8 +1588,7 @@ int_const_binop (code, arg1, arg2, notrunc, forsize)
low = 1, hi = 0;
break;
}
overflow = div_and_round_double (code, uns,
int1l, int1h, int2l, int2h,
overflow = div_and_round_double (code, uns, int1l, int1h, int2l, int2h,
&low, &hi, &garbagel, &garbageh);
break;
@ -1632,9 +1636,14 @@ int_const_binop (code, arg1, arg2, notrunc, forsize)
abort ();
}
if (forsize && hi == 0 && low < 10000
/* If this is for a sizetype, can be represented as one (signed)
HOST_WIDE_INT word, and doesn't overflow, use size_int since it caches
constants. */
if (is_sizetype
&& ((hi == 0 && (HOST_WIDE_INT) low >= 0)
|| (hi == -1 && (HOST_WIDE_INT) low < 0))
&& overflow == 0 && ! TREE_OVERFLOW (arg1) && ! TREE_OVERFLOW (arg2))
return size_int_type_wide (low, TREE_TYPE (arg1));
return size_int_type_wide (low, type);
else
{
t = build_int_2 (low, hi);
@ -1642,14 +1651,16 @@ int_const_binop (code, arg1, arg2, notrunc, forsize)
}
TREE_OVERFLOW (t)
= ((notrunc ? (!uns || forsize) && overflow
: force_fit_type (t, (!uns || forsize) && overflow) && ! no_overflow)
= ((notrunc
? (!uns || is_sizetype) && overflow
: (force_fit_type (t, (!uns || is_sizetype) && overflow)
&& ! no_overflow))
| TREE_OVERFLOW (arg1)
| TREE_OVERFLOW (arg2));
/* If we're doing a size calculation, unsigned arithmetic does overflow.
So check if force_fit_type truncated the value. */
if (forsize
if (is_sizetype
&& ! TREE_OVERFLOW (t)
&& (TREE_INT_CST_HIGH (t) != hi
|| TREE_INT_CST_LOW (t) != low))
@ -1740,7 +1751,7 @@ const_binop (code, arg1, arg2, notrunc)
STRIP_NOPS (arg2);
if (TREE_CODE (arg1) == INTEGER_CST)
return int_const_binop (code, arg1, arg2, notrunc, 0);
return int_const_binop (code, arg1, arg2, notrunc);
#if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
if (TREE_CODE (arg1) == REAL_CST)
@ -1865,6 +1876,39 @@ const_binop (code, arg1, arg2, notrunc)
}
return 0;
}
/* These are the hash table functions for the hash table of INTEGER_CST
nodes of a sizetype. */
/* Return the hash code code X, an INTEGER_CST. */
static hashval_t
size_htab_hash (x)
const void *x;
{
tree t = (tree) x;
return (TREE_INT_CST_HIGH (t) ^ TREE_INT_CST_LOW (t)
^ (hashval_t) ((long) TREE_TYPE (t) >> 3)
^ (TREE_OVERFLOW (t) << 20));
}
/* Return non-zero 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
size_htab_eq (x, y)
const void *x;
const void *y;
{
tree xt = (tree) x;
tree yt = (tree) y;
return (TREE_INT_CST_HIGH (xt) == TREE_INT_CST_HIGH (yt)
&& TREE_INT_CST_LOW (xt) == TREE_INT_CST_LOW (yt)
&& TREE_TYPE (xt) == TREE_TYPE (yt)
&& TREE_OVERFLOW (xt) == TREE_OVERFLOW (yt));
}
/* Return an INTEGER_CST with value whose low-order HOST_BITS_PER_WIDE_INT
bits are given by NUMBER and of the sizetype represented by KIND. */
@ -1884,40 +1928,38 @@ size_int_type_wide (number, type)
HOST_WIDE_INT number;
tree type;
{
/* Type-size nodes already made for small sizes. */
static tree size_table[2048 + 1];
static int init_p = 0;
tree t;
static htab_t size_htab = 0;
static tree new_const = 0;
PTR *slot;
if (! init_p)
if (size_htab == 0)
{
ggc_add_tree_root ((tree *) size_table,
sizeof size_table / sizeof (tree));
init_p = 1;
size_htab = htab_create (1024, size_htab_hash, size_htab_eq, NULL);
ggc_add_deletable_htab (size_htab, NULL, NULL);
new_const = make_node (INTEGER_CST);
ggc_add_tree_root (&new_const, 1);
}
/* If this is a positive number that fits in the table we use to hold
cached entries, see if it is already in the table and put it there
if not. */
if (number >= 0 && number < (int) ARRAY_SIZE (size_table))
/* Adjust NEW_CONST to be the constant we want. If it's already in the
hash table, we return the value from the hash table. Otherwise, we
place that in the hash table and make a new node for the next time. */
TREE_INT_CST_LOW (new_const) = number;
TREE_INT_CST_HIGH (new_const) = number < 0 ? -1 : 0;
TREE_TYPE (new_const) = type;
TREE_OVERFLOW (new_const) = TREE_CONSTANT_OVERFLOW (new_const)
= force_fit_type (new_const, 0);
slot = htab_find_slot (size_htab, new_const, INSERT);
if (*slot == 0)
{
if (size_table[number] != 0)
for (t = size_table[number]; t != 0; t = TREE_CHAIN (t))
if (TREE_TYPE (t) == type)
return t;
t = build_int_2 (number, 0);
TREE_TYPE (t) = type;
TREE_CHAIN (t) = size_table[number];
size_table[number] = t;
tree t = new_const;
*slot = (PTR) new_const;
new_const = make_node (INTEGER_CST);
return t;
}
t = build_int_2 (number, number < 0 ? -1 : 0);
TREE_TYPE (t) = type;
TREE_OVERFLOW (t) = TREE_CONSTANT_OVERFLOW (t) = force_fit_type (t, 0);
return t;
else
return (tree) *slot;
}
/* Combine operands OP1 and OP2 with arithmetic operation CODE. CODE
@ -1949,7 +1991,7 @@ size_binop (code, arg0, arg1)
return arg1;
/* Handle general case of two integer constants. */
return int_const_binop (code, arg0, arg1, 0, 1);
return int_const_binop (code, arg0, arg1, 0);
}
if (arg0 == error_mark_node || arg1 == error_mark_node)

View File

@ -27,6 +27,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "tree.h"
#include "tm_p.h"
#include "hash.h"
#include "hashtab.h"
#include "varray.h"
#include "ggc.h"
@ -47,9 +48,10 @@ static void ggc_mark_tree_ptr PARAMS ((void *));
static void ggc_mark_rtx_varray_ptr PARAMS ((void *));
static void ggc_mark_tree_varray_ptr PARAMS ((void *));
static void ggc_mark_tree_hash_table_ptr PARAMS ((void *));
static int ggc_htab_delete PARAMS ((void **, void *));
static void ggc_mark_trees PARAMS ((void));
static bool ggc_mark_tree_hash_table_entry PARAMS ((struct hash_entry *,
hash_table_key));
hash_table_key));
/* Maintain global roots that are preserved during GC. */
@ -166,12 +168,79 @@ ggc_del_root (base)
abort();
}
/* Add a hash table to be scanned when all roots have been processed. We
delete any entry in the table that has not been marked. */
struct d_htab_root
{
struct d_htab_root *next;
htab_t htab;
ggc_htab_marked_p marked_p;
ggc_htab_mark mark;
};
static struct d_htab_root *d_htab_roots;
/* Add X, an htab, to a list of htabs that contain objects which are allocated
from GC memory. Once all other roots are marked, we check each object in
the htab to see if it has already been marked. If not, it is deleted.
MARKED_P, if specified, is a function that returns 1 if the entry is to
be considered as "marked". If not present, the data structure pointed to
by the htab slot is tested. This function should be supplied if some
other object (such as something pointed to by that object) should be tested
in which case the function tests whether that object (or objects) are
marked (using ggc_marked_p) and returns nonzero if it is.
MARK, if specified, is a function that is passed the contents of a slot
that has been determined to have been "marked" (via the above function)
and marks any other objects pointed to by that object. For example,
we might have a hash table of memory attribute blocks, which are pointed
to by a MEM RTL but have a pointer to a DECL. MARKED_P in that case will
not be specified because we want to know if the attribute block is pointed
to by the MEM, but MARK must be specified because if the block has been
marked, we need to mark the DECL. */
void
ggc_add_deletable_htab (x, marked_p, mark)
PTR x;
ggc_htab_marked_p marked_p;
ggc_htab_mark mark;
{
struct d_htab_root *r
= (struct d_htab_root *) xmalloc (sizeof (struct d_htab_root));
r->next = d_htab_roots;
r->htab = (htab_t) x;
r->marked_p = marked_p ? marked_p : ggc_marked_p;
r->mark = mark;
d_htab_roots = r;
}
/* Process a slot of an htab by deleting it if it has not been marked. */
static int
ggc_htab_delete (slot, info)
void **slot;
void *info;
{
struct d_htab_root *r = (struct d_htab_root *) info;
if (! (*r->marked_p) (*slot))
htab_clear_slot (r->htab, slot);
else if (r->mark)
(*r->mark) (*slot);
return 1;
}
/* Iterate through all registered roots and mark each element. */
void
ggc_mark_roots ()
{
struct ggc_root* x;
struct ggc_root *x;
struct d_htab_root *y;
VARRAY_TREE_INIT (ggc_pending_trees, 4096, "ggc_pending_trees");
@ -189,6 +258,16 @@ ggc_mark_roots ()
/* Mark all the queued up trees, and their children. */
ggc_mark_trees ();
VARRAY_FREE (ggc_pending_trees);
/* Now scan all hash tables that have objects which are to be deleted if
they are not already marked. Since these may mark more trees, we need
to reinitialize that varray. */
VARRAY_TREE_INIT (ggc_pending_trees, 1024, "ggc_pending_trees");
for (y = d_htab_roots; y != NULL; y = y->next)
htab_traverse (y->htab, ggc_htab_delete, (PTR) y);
ggc_mark_trees ();
VARRAY_FREE (ggc_pending_trees);
}
/* R had not been previously marked, but has now been marked via
@ -463,7 +542,7 @@ ggc_mark_tree_varray (v)
ggc_mark_tree (VARRAY_TREE (v, i));
}
/* Mark the hash table-entry HE. It's key field is really a tree. */
/* Mark the hash table-entry HE. Its key field is really a tree. */
static bool
ggc_mark_tree_hash_table_entry (he, k)

View File

@ -1001,6 +1001,35 @@ ggc_set_mark (p)
return 0;
}
/* Return 1 if P has been marked, zero otherwise.
P must have been allocated by the GC allocator; it mustn't point to
static objects, stack variables, or memory allocated with malloc. */
int
ggc_marked_p (p)
const void *p;
{
page_entry *entry;
unsigned bit, word;
unsigned long mask;
/* Look up the page on which the object is alloced. If the object
wasn't allocated by the collector, we'll probably die. */
entry = lookup_page_table_entry (p);
#ifdef ENABLE_CHECKING
if (entry == NULL)
abort ();
#endif
/* Calculate the index of the object on the page; this is its bit
position in the in_use_p bitmap. */
bit = (((const char *) p) - entry->page) / OBJECT_SIZE (entry->order);
word = bit / HOST_BITS_PER_LONG;
mask = (unsigned long) 1 << (bit % HOST_BITS_PER_LONG);
return entry->in_use_p[word] & mask;
}
/* Return the size of the gc-able object P. */
size_t

View File

@ -228,6 +228,23 @@ ggc_set_mark (p)
return 0;
}
/* Return 1 if P has been marked, zero otherwise. */
int
ggc_marked_p (p)
const void *p;
{
struct ggc_mem *x;
x = (struct ggc_mem *) ((const char *)p - offsetof (struct ggc_mem, u));
#ifdef GGC_ALWAYS_VERIFY
if (! tree_lookup (x))
abort ();
#endif
return x->mark;
}
/* Return the size of the gc-able object P. */
size_t

View File

@ -47,23 +47,39 @@ extern const char digit_vector[]; /* "0" .. "9" */
extern varray_type ggc_pending_trees;
/* Manipulate global roots that are needed between calls to gc. */
void ggc_add_root PARAMS ((void *base, int nelt, int size, void (*)(void *)));
void ggc_add_rtx_root PARAMS ((struct rtx_def **, int nelt));
void ggc_add_tree_root PARAMS ((union tree_node **, int nelt));
void ggc_add_rtx_varray_root PARAMS ((struct varray_head_tag **, int nelt));
void ggc_add_tree_varray_root PARAMS ((struct varray_head_tag **, int nelt));
void ggc_add_tree_hash_table_root PARAMS ((struct hash_table **, int nelt));
void ggc_del_root PARAMS ((void *base));
extern void ggc_add_root PARAMS ((void *base, int nelt,
int size, void (*)(void *)));
extern void ggc_add_rtx_root PARAMS ((struct rtx_def **, int nelt));
extern void ggc_add_tree_root PARAMS ((union tree_node **,
int nelt));
extern void ggc_add_rtx_varray_root PARAMS ((struct varray_head_tag **,
int nelt));
extern void ggc_add_tree_varray_root PARAMS ((struct varray_head_tag **,
int nelt));
extern void ggc_add_tree_hash_table_root PARAMS ((struct hash_table **,
int nelt));
extern void ggc_del_root PARAMS ((void *base));
/* Types used for mark test and marking functions, if specified, in call
below. */
typedef int (*ggc_htab_marked_p) PARAMS ((const void *));
typedef void (*ggc_htab_mark) PARAMS ((const void *));
/* Add a hash table to be scanned when all roots have been processed. We
delete any entry in the table that has not been marked. The argument is
really htab_t. */
extern void ggc_add_deletable_htab PARAMS ((PTR, ggc_htab_marked_p,
ggc_htab_mark));
/* Mark nodes from the gc_add_root callback. These functions follow
pointers to mark other objects too. */
extern void ggc_mark_rtx_varray PARAMS ((struct varray_head_tag *));
extern void ggc_mark_tree_varray PARAMS ((struct varray_head_tag *));
extern void ggc_mark_tree_hash_table PARAMS ((struct hash_table *));
extern void ggc_mark_roots PARAMS ((void));
extern void ggc_mark_rtx_varray PARAMS ((struct varray_head_tag *));
extern void ggc_mark_tree_varray PARAMS ((struct varray_head_tag *));
extern void ggc_mark_tree_hash_table PARAMS ((struct hash_table *));
extern void ggc_mark_roots PARAMS ((void));
extern void ggc_mark_rtx_children PARAMS ((struct rtx_def *));
extern void ggc_mark_rtvec_children PARAMS ((struct rtvec_def *));
extern void ggc_mark_rtx_children PARAMS ((struct rtx_def *));
extern void ggc_mark_rtvec_children PARAMS ((struct rtvec_def *));
/* If EXPR is not NULL and previously unmarked, mark it and evaluate
to true. Otherwise evaluate to false. */
@ -108,23 +124,23 @@ extern void ggc_mark_rtvec_children PARAMS ((struct rtvec_def *));
/* A GC implementation must provide these functions. */
/* Initialize the garbage collector. */
extern void init_ggc PARAMS ((void));
extern void init_stringpool PARAMS ((void));
extern void init_ggc PARAMS ((void));
extern void init_stringpool PARAMS ((void));
/* Start a new GGC context. Memory allocated in previous contexts
will not be collected while the new context is active. */
extern void ggc_push_context PARAMS ((void));
extern void ggc_push_context PARAMS ((void));
/* Finish a GC context. Any uncollected memory in the new context
will be merged with the old context. */
extern void ggc_pop_context PARAMS ((void));
extern void ggc_pop_context PARAMS ((void));
/* Allocation. */
/* The internal primitive. */
void *ggc_alloc PARAMS ((size_t));
extern void *ggc_alloc PARAMS ((size_t));
/* Like ggc_alloc, but allocates cleared memory. */
void *ggc_alloc_cleared PARAMS ((size_t));
extern void *ggc_alloc_cleared PARAMS ((size_t));
#define ggc_alloc_rtx(NSLOTS) \
((struct rtx_def *) ggc_alloc (sizeof (struct rtx_def) \
@ -139,27 +155,33 @@ void *ggc_alloc_cleared PARAMS ((size_t));
/* Allocate a gc-able string, and fill it with LENGTH bytes from CONTENTS.
If LENGTH is -1, then CONTENTS is assumed to be a
null-terminated string and the memory sized accordingly. */
const char *ggc_alloc_string PARAMS ((const char *contents, int length));
extern const char *ggc_alloc_string PARAMS ((const char *contents,
int length));
/* Make a copy of S, in GC-able memory. */
#define ggc_strdup(S) ggc_alloc_string((S), -1)
/* Invoke the collector. Garbage collection occurs only when this
function is called, not during allocations. */
void ggc_collect PARAMS ((void));
extern void ggc_collect PARAMS ((void));
/* Actually set the mark on a particular region of memory, but don't
follow pointers. This function is called by ggc_mark_*. It
returns zero if the object was not previously marked; non-zero if
the object was already marked, or if, for any other reason,
pointers in this data structure should not be traversed. */
int ggc_set_mark PARAMS ((const void *));
extern int ggc_set_mark PARAMS ((const void *));
/* Return 1 if P has been marked, zero otherwise.
P must have been allocated by the GC allocator; it mustn't point to
static objects, stack variables, or memory allocated with malloc. */
extern int ggc_marked_p PARAMS ((const void *));
/* Callbacks to the languages. */
/* This is the language's opportunity to mark nodes held through
the lang_specific hooks in the tree. */
void lang_mark_tree PARAMS ((union tree_node *));
extern void lang_mark_tree PARAMS ((union tree_node *));
/* The FALSE_LABEL_STACK, declared in except.h, has language-dependent
semantics. If a front-end needs to mark the false label stack, it
@ -169,12 +191,12 @@ extern void (*lang_mark_false_label_stack) PARAMS ((struct label_node *));
/* Mark functions for various structs scattered about. */
void mark_eh_status PARAMS ((struct eh_status *));
void mark_emit_status PARAMS ((struct emit_status *));
void mark_expr_status PARAMS ((struct expr_status *));
void mark_stmt_status PARAMS ((struct stmt_status *));
void mark_varasm_status PARAMS ((struct varasm_status *));
void mark_optab PARAMS ((void *));
void mark_eh_status PARAMS ((struct eh_status *));
void mark_emit_status PARAMS ((struct emit_status *));
void mark_expr_status PARAMS ((struct expr_status *));
void mark_stmt_status PARAMS ((struct stmt_status *));
void mark_varasm_status PARAMS ((struct varasm_status *));
void mark_optab PARAMS ((void *));
/* Statistics. */
@ -203,12 +225,12 @@ typedef struct ggc_statistics
} ggc_statistics;
/* Return the number of bytes allocated at the indicated address. */
size_t ggc_get_size PARAMS ((const void *));
extern size_t ggc_get_size PARAMS ((const void *));
/* Used by the various collectors to gather and print statistics that
do not depend on the collector in use. */
void ggc_print_common_statistics PARAMS ((FILE *, ggc_statistics *));
extern void ggc_print_common_statistics PARAMS ((FILE *, ggc_statistics *));
/* Print allocation statistics. */
extern void ggc_print_statistics PARAMS ((void));
void stringpool_statistics PARAMS ((void));
extern void ggc_print_statistics PARAMS ((void));
extern void stringpool_statistics PARAMS ((void));

View File

@ -158,12 +158,12 @@ htab_t type_hash_table;
static void build_real_from_int_cst_1 PARAMS ((PTR));
static void set_type_quals PARAMS ((tree, int));
static void append_random_chars PARAMS ((char *));
static void mark_type_hash PARAMS ((void *));
static int type_hash_eq PARAMS ((const void*, const void*));
static unsigned int type_hash_hash PARAMS ((const void*));
static void print_type_hash_statistics PARAMS((void));
static int mark_hash_entry PARAMS((void **, void *));
static void finish_vector_type PARAMS((tree));
static int type_hash_marked_p PARAMS ((const void *));
static void type_hash_mark PARAMS ((const void *));
static int mark_tree_hashtable_entry PARAMS((void **, void *));
/* If non-null, these are language-specific helper functions for
@ -225,7 +225,8 @@ init_obstacks ()
/* Initialize the hash table of types. */
type_hash_table = htab_create (TYPE_HASH_INITIAL_SIZE, type_hash_hash,
type_hash_eq, 0);
ggc_add_root (&type_hash_table, 1, sizeof type_hash_table, mark_type_hash);
ggc_add_deletable_htab (type_hash_table, type_hash_marked_p,
type_hash_mark);
ggc_add_tree_root (global_trees, TI_MAX);
ggc_add_tree_root (integer_types, itk_none);
@ -3186,7 +3187,7 @@ type_hash_add (hashcode, type)
struct type_hash *h;
void **loc;
h = (struct type_hash *) permalloc (sizeof (struct type_hash));
h = (struct type_hash *) ggc_alloc (sizeof (struct type_hash));
h->hash = hashcode;
h->type = type;
loc = htab_find_slot_with_hash (type_hash_table, h, hashcode, INSERT);
@ -3217,6 +3218,8 @@ type_hash_canon (hashcode, type)
if (debug_no_type_hash)
return type;
/* See if the type is in the hash table already. If so, return it.
Otherwise, add the type. */
t1 = type_hash_lookup (hashcode, type);
if (t1 != 0)
{
@ -3226,37 +3229,29 @@ type_hash_canon (hashcode, type)
#endif
return t1;
}
/* If this is a permanent type, record it for later reuse. */
type_hash_add (hashcode, type);
return type;
else
{
type_hash_add (hashcode, type);
return type;
}
}
/* Callback function for htab_traverse. */
/* See if the data pointed to by the type hash table is marked. */
static int
mark_hash_entry (entry, param)
void **entry;
void *param ATTRIBUTE_UNUSED;
type_hash_marked_p (p)
const void *p;
{
struct type_hash *p = *(struct type_hash **) entry;
ggc_mark_tree (p->type);
/* Continue scan. */
return 1;
return ggc_marked_p (((struct type_hash *) p)->type);
}
/* Mark ARG (which is really a htab_t *) for GC. */
/* Mark the entry in the type hash table the type it points to is marked. */
static void
mark_type_hash (arg)
void *arg;
type_hash_mark (p)
const void *p;
{
htab_t t = *(htab_t *) arg;
htab_traverse (t, mark_hash_entry, 0);
ggc_mark (p);
}
/* Mark the hashtable slot pointed to by ENTRY (which is really a