OSDN Git Service

* c-decl.c: (start_struct): Commonize flag setting.
[pf3gnuchains/gcc-fork.git] / gcc / ggc-common.c
1 /* Simple garbage collection for the GNU compiler.
2    Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
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.
10
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.
15
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.  */
20
21 /* Generic garbage collection (GC) functions and data, not specific to
22    any particular GC implementation.  */
23
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
39
40 /* Statistics about the allocation.  */
41 static ggc_statistics *ggc_stats;
42
43 static int ggc_htab_delete PARAMS ((void **, void *));
44
45 /* Maintain global roots that are preserved during GC.  */
46
47 /* Global roots that are preserved during calls to gc.  */
48
49 struct ggc_root
50 {
51   struct ggc_root *next;
52   void *base;
53   int nelt;
54   int size;
55   void (*cb) PARAMS ((void *));
56 };
57
58 static struct ggc_root *roots;
59
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.  */
65
66 void
67 ggc_add_root (base, nelt, size, cb)
68      void *base;
69      int nelt, size;
70      void (*cb) PARAMS ((void *));
71 {
72   struct ggc_root *x = (struct ggc_root *) xmalloc (sizeof (*x));
73
74   x->next = roots;
75   x->base = base;
76   x->nelt = nelt;
77   x->size = size;
78   x->cb = cb;
79
80   roots = x;
81 }
82
83 /* Process a slot of an htab by deleting it if it has not been marked.  */
84
85 static int
86 ggc_htab_delete (slot, info)
87      void **slot;
88      void *info;
89 {
90   const struct ggc_cache_tab *r = (const struct ggc_cache_tab *) info;
91
92   if (! (*r->marked_p) (*slot))
93     htab_clear_slot (*r->base, slot);
94   else
95     (*r->cb) (*slot);
96
97   return 1;
98 }
99
100 /* Iterate through all registered roots and mark each element.  */
101
102 void
103 ggc_mark_roots ()
104 {
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;
111
112   for (rt = gt_ggc_deletable_rtab; *rt; rt++)
113     for (rti = *rt; rti->base != NULL; rti++)
114       memset (rti->base, 0, rti->stride);
115
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));
120
121   for (x = roots; x != NULL; x = x->next)
122     {
123       char *elt = x->base;
124       int s = x->size, n = x->nelt;
125       void (*cb) PARAMS ((void *)) = x->cb;
126       int i;
127
128       for (i = 0; i < n; ++i, elt += s)
129         (*cb)(elt);
130     }
131
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);
138 }
139
140 /* Allocate a block of memory, then clear it.  */
141 void *
142 ggc_alloc_cleared (size)
143      size_t size;
144 {
145   void *buf = ggc_alloc (size);
146   memset (buf, 0, size);
147   return buf;
148 }
149
150 /* Resize a block of memory, possibly re-allocating it.  */
151 void *
152 ggc_realloc (x, size)
153      void *x;
154      size_t size;
155 {
156   void *r;
157   size_t old_size;
158
159   if (x == NULL)
160     return ggc_alloc (size);
161
162   old_size = ggc_get_size (x);
163   if (size <= old_size)
164     {
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;
179     }
180
181   r = ggc_alloc (size);
182
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));
188
189   memcpy (r, x, old_size);
190
191   /* The old object is not supposed to be used anymore.  */
192   VALGRIND_DISCARD (VALGRIND_MAKE_NOACCESS (x, old_size));
193
194   return r;
195 }
196
197 /* Like ggc_alloc_cleared, but performs a multiplication.  */
198 void *
199 ggc_calloc (s1, s2)
200      size_t s1, s2;
201 {
202   return ggc_alloc_cleared (s1 * s2);
203 }
204
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'))
212
213 void
214 ggc_print_common_statistics (stream, stats)
215      FILE *stream;
216      ggc_statistics *stats;
217 {
218   int code;
219
220   /* Set the pointer so that during collection we will actually gather
221      the statistics.  */
222   ggc_stats = stats;
223
224   /* Then do one collection to fill in the statistics.  */
225   ggc_collect ();
226
227   /* Total the statistics.  */
228   for (code = 0; code < MAX_TREE_CODES; ++code)
229     {
230       stats->total_num_trees += stats->num_trees[code];
231       stats->total_size_trees += stats->size_trees[code];
232     }
233   for (code = 0; code < NUM_RTX_CODE; ++code)
234     {
235       stats->total_num_rtxs += stats->num_rtxs[code];
236       stats->total_size_rtxs += stats->size_rtxs[code];
237     }
238
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])
244       {
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));
252       }
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));
258
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])
264       {
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));
272       }
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));
278
279   /* Don't gather statistics any more.  */
280   ggc_stats = NULL;
281 }