* sh.md (movdi_i): Name. Remove inappropriate comment.
[official-gcc.git] / gcc / ggc-common.c
blobb0ebabc40ce6ff4bf4019bb6415ea9713cc061f3
1 /* Simple garbage collection for the GNU compiler.
2 Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 2, or (at your option) any later
9 version.
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 for more details.
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING. If not, write to the Free
18 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19 02111-1307, USA. */
21 /* Generic garbage collection (GC) functions and data, not specific to
22 any particular GC implementation. */
24 #include "config.h"
25 #include "system.h"
26 #include "rtl.h"
27 #include "tree.h"
28 #include "tm_p.h"
29 #include "hashtab.h"
30 #include "varray.h"
31 #include "ggc.h"
32 #include "langhooks.h"
33 #ifdef ENABLE_VALGRIND_CHECKING
34 #include <valgrind.h>
35 #else
36 /* Avoid #ifdef:s when we can help it. */
37 #define VALGRIND_DISCARD(x)
38 #endif
40 /* Statistics about the allocation. */
41 static ggc_statistics *ggc_stats;
43 static int ggc_htab_delete PARAMS ((void **, void *));
45 /* Maintain global roots that are preserved during GC. */
47 /* Global roots that are preserved during calls to gc. */
49 struct ggc_root
51 struct ggc_root *next;
52 void *base;
53 int nelt;
54 int size;
55 void (*cb) PARAMS ((void *));
58 static struct ggc_root *roots;
60 /* Add BASE as a new garbage collection root. It is an array of
61 length NELT with each element SIZE bytes long. CB is a
62 function that will be called with a pointer to each element
63 of the array; it is the intention that CB call the appropriate
64 routine to mark gc-able memory for that element. */
66 void
67 ggc_add_root (base, nelt, size, cb)
68 void *base;
69 int nelt, size;
70 void (*cb) PARAMS ((void *));
72 struct ggc_root *x = (struct ggc_root *) xmalloc (sizeof (*x));
74 x->next = roots;
75 x->base = base;
76 x->nelt = nelt;
77 x->size = size;
78 x->cb = cb;
80 roots = x;
83 /* Process a slot of an htab by deleting it if it has not been marked. */
85 static int
86 ggc_htab_delete (slot, info)
87 void **slot;
88 void *info;
90 const struct ggc_cache_tab *r = (const struct ggc_cache_tab *) info;
92 if (! (*r->marked_p) (*slot))
93 htab_clear_slot (*r->base, slot);
94 else
95 (*r->cb) (*slot);
97 return 1;
100 /* Iterate through all registered roots and mark each element. */
102 void
103 ggc_mark_roots ()
105 struct ggc_root *x;
106 const struct ggc_root_tab *const *rt;
107 const struct ggc_root_tab *rti;
108 const struct ggc_cache_tab *const *ct;
109 const struct ggc_cache_tab *cti;
110 size_t i;
112 for (rt = gt_ggc_deletable_rtab; *rt; rt++)
113 for (rti = *rt; rti->base != NULL; rti++)
114 memset (rti->base, 0, rti->stride);
116 for (rt = gt_ggc_rtab; *rt; rt++)
117 for (rti = *rt; rti->base != NULL; rti++)
118 for (i = 0; i < rti->nelt; i++)
119 (*rti->cb)(*(void **)((char *)rti->base + rti->stride * i));
121 for (x = roots; x != NULL; x = x->next)
123 char *elt = x->base;
124 int s = x->size, n = x->nelt;
125 void (*cb) PARAMS ((void *)) = x->cb;
126 int i;
128 for (i = 0; i < n; ++i, elt += s)
129 (*cb)(elt);
132 /* Now scan all hash tables that have objects which are to be deleted if
133 they are not already marked. */
134 for (ct = gt_ggc_cache_rtab; *ct; ct++)
135 for (cti = *ct; cti->base != NULL; cti++)
136 if (*cti->base)
137 htab_traverse (*cti->base, ggc_htab_delete, (PTR) cti);
140 /* Allocate a block of memory, then clear it. */
141 void *
142 ggc_alloc_cleared (size)
143 size_t size;
145 void *buf = ggc_alloc (size);
146 memset (buf, 0, size);
147 return buf;
150 /* Resize a block of memory, possibly re-allocating it. */
151 void *
152 ggc_realloc (x, size)
153 void *x;
154 size_t size;
156 void *r;
157 size_t old_size;
159 if (x == NULL)
160 return ggc_alloc (size);
162 old_size = ggc_get_size (x);
163 if (size <= old_size)
165 /* Mark the unwanted memory as unaccessible. We also need to make
166 the "new" size accessible, since ggc_get_size returns the size of
167 the pool, not the size of the individually allocated object, the
168 size which was previously made accessible. Unfortunately, we
169 don't know that previously allocated size. Without that
170 knowledge we have to lose some initialization-tracking for the
171 old parts of the object. An alternative is to mark the whole
172 old_size as reachable, but that would lose tracking of writes
173 after the end of the object (by small offsets). Discard the
174 handle to avoid handle leak. */
175 VALGRIND_DISCARD (VALGRIND_MAKE_NOACCESS ((char *) x + size,
176 old_size - size));
177 VALGRIND_DISCARD (VALGRIND_MAKE_READABLE (x, size));
178 return x;
181 r = ggc_alloc (size);
183 /* Since ggc_get_size returns the size of the pool, not the size of the
184 individually allocated object, we'd access parts of the old object
185 that were marked invalid with the memcpy below. We lose a bit of the
186 initialization-tracking since some of it may be uninitialized. */
187 VALGRIND_DISCARD (VALGRIND_MAKE_READABLE (x, old_size));
189 memcpy (r, x, old_size);
191 /* The old object is not supposed to be used anymore. */
192 VALGRIND_DISCARD (VALGRIND_MAKE_NOACCESS (x, old_size));
194 return r;
197 /* Like ggc_alloc_cleared, but performs a multiplication. */
198 void *
199 ggc_calloc (s1, s2)
200 size_t s1, s2;
202 return ggc_alloc_cleared (s1 * s2);
205 /* Print statistics that are independent of the collector in use. */
206 #define SCALE(x) ((unsigned long) ((x) < 1024*10 \
207 ? (x) \
208 : ((x) < 1024*1024*10 \
209 ? (x) / 1024 \
210 : (x) / (1024*1024))))
211 #define LABEL(x) ((x) < 1024*10 ? ' ' : ((x) < 1024*1024*10 ? 'k' : 'M'))
213 void
214 ggc_print_common_statistics (stream, stats)
215 FILE *stream;
216 ggc_statistics *stats;
218 int code;
220 /* Set the pointer so that during collection we will actually gather
221 the statistics. */
222 ggc_stats = stats;
224 /* Then do one collection to fill in the statistics. */
225 ggc_collect ();
227 /* Total the statistics. */
228 for (code = 0; code < MAX_TREE_CODES; ++code)
230 stats->total_num_trees += stats->num_trees[code];
231 stats->total_size_trees += stats->size_trees[code];
233 for (code = 0; code < NUM_RTX_CODE; ++code)
235 stats->total_num_rtxs += stats->num_rtxs[code];
236 stats->total_size_rtxs += stats->size_rtxs[code];
239 /* Print the statistics for trees. */
240 fprintf (stream, "\n%-17s%10s %16s %10s\n", "Tree",
241 "Number", "Bytes", "% Total");
242 for (code = 0; code < MAX_TREE_CODES; ++code)
243 if (ggc_stats->num_trees[code])
245 fprintf (stream, "%-17s%10u%16ld%c %10.3f\n",
246 tree_code_name[code],
247 ggc_stats->num_trees[code],
248 SCALE (ggc_stats->size_trees[code]),
249 LABEL (ggc_stats->size_trees[code]),
250 (100 * ((double) ggc_stats->size_trees[code])
251 / ggc_stats->total_size_trees));
253 fprintf (stream,
254 "%-17s%10u%16ld%c\n", "Total",
255 ggc_stats->total_num_trees,
256 SCALE (ggc_stats->total_size_trees),
257 LABEL (ggc_stats->total_size_trees));
259 /* Print the statistics for RTL. */
260 fprintf (stream, "\n%-17s%10s %16s %10s\n", "RTX",
261 "Number", "Bytes", "% Total");
262 for (code = 0; code < NUM_RTX_CODE; ++code)
263 if (ggc_stats->num_rtxs[code])
265 fprintf (stream, "%-17s%10u%16ld%c %10.3f\n",
266 rtx_name[code],
267 ggc_stats->num_rtxs[code],
268 SCALE (ggc_stats->size_rtxs[code]),
269 LABEL (ggc_stats->size_rtxs[code]),
270 (100 * ((double) ggc_stats->size_rtxs[code])
271 / ggc_stats->total_size_rtxs));
273 fprintf (stream,
274 "%-17s%10u%16ld%c\n", "Total",
275 ggc_stats->total_num_rtxs,
276 SCALE (ggc_stats->total_size_rtxs),
277 LABEL (ggc_stats->total_size_rtxs));
279 /* Don't gather statistics any more. */
280 ggc_stats = NULL;