]>
git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/ggc-common.c
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
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
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
21 /* Generic garbage collection (GC) functions and data, not specific to
22 any particular GC implementation. */
32 #include "langhooks.h"
34 /* Statistics about the allocation. */
35 static ggc_statistics
*ggc_stats
;
37 static void ggc_mark_rtx_children_1
PARAMS ((rtx
));
38 static int ggc_htab_delete
PARAMS ((void **, void *));
40 /* Maintain global roots that are preserved during GC. */
42 /* Global roots that are preserved during calls to gc. */
46 struct ggc_root
*next
;
50 void (*cb
) PARAMS ((void *));
53 static struct ggc_root
*roots
;
55 /* Add BASE as a new garbage collection root. It is an array of
56 length NELT with each element SIZE bytes long. CB is a
57 function that will be called with a pointer to each element
58 of the array; it is the intention that CB call the appropriate
59 routine to mark gc-able memory for that element. */
62 ggc_add_root (base
, nelt
, size
, cb
)
65 void (*cb
) PARAMS ((void *));
67 struct ggc_root
*x
= (struct ggc_root
*) xmalloc (sizeof (*x
));
78 /* Process a slot of an htab by deleting it if it has not been marked. */
81 ggc_htab_delete (slot
, info
)
85 const struct ggc_cache_tab
*r
= (const struct ggc_cache_tab
*) info
;
87 if (! (*r
->marked_p
) (*slot
))
88 htab_clear_slot (*r
->base
, slot
);
95 /* Iterate through all registered roots and mark each element. */
101 const struct ggc_root_tab
*const *rt
;
102 const struct ggc_root_tab
*rti
;
103 const struct ggc_cache_tab
*const *ct
;
104 const struct ggc_cache_tab
*cti
;
107 for (rt
= gt_ggc_deletable_rtab
; *rt
; rt
++)
108 for (rti
= *rt
; rti
->base
!= NULL
; rti
++)
109 memset (rti
->base
, 0, rti
->stride
);
111 for (rt
= gt_ggc_rtab
; *rt
; rt
++)
112 for (rti
= *rt
; rti
->base
!= NULL
; rti
++)
113 for (i
= 0; i
< rti
->nelt
; i
++)
114 (*rti
->cb
)(*(void **)((char *)rti
->base
+ rti
->stride
* i
));
116 for (x
= roots
; x
!= NULL
; x
= x
->next
)
119 int s
= x
->size
, n
= x
->nelt
;
120 void (*cb
) PARAMS ((void *)) = x
->cb
;
123 for (i
= 0; i
< n
; ++i
, elt
+= s
)
127 /* Now scan all hash tables that have objects which are to be deleted if
128 they are not already marked. */
129 for (ct
= gt_ggc_cache_rtab
; *ct
; ct
++)
130 for (cti
= *ct
; cti
->base
!= NULL
; cti
++)
131 htab_traverse (*cti
->base
, ggc_htab_delete
, (PTR
) cti
);
134 /* R had not been previously marked, but has now been marked via
135 ggc_set_mark. Now recurse and process the children. */
138 ggc_mark_rtx_children (r
)
143 /* Special case the instruction chain. This is a data structure whose
144 chain length is potentially unbounded, and which contain references
145 within the chain (e.g. label_ref and insn_list). If do nothing here,
146 we risk blowing the stack recursing through a long chain of insns.
148 Combat this by marking all of the instructions in the chain before
149 marking the contents of those instructions. */
151 switch (GET_CODE (r
))
159 for (i
= NEXT_INSN (r
); ; i
= NEXT_INSN (i
))
160 if (! ggc_test_and_set_mark (i
))
164 for (i
= NEXT_INSN (r
); i
!= last
; i
= NEXT_INSN (i
))
165 ggc_mark_rtx_children_1 (i
);
171 ggc_mark_rtx_children_1 (r
);
175 ggc_mark_rtx_children_1 (r
)
184 enum rtx_code code
= GET_CODE (r
);
185 /* This gets set to a child rtx to eliminate tail recursion. */
188 /* Collect statistics, if appropriate. */
191 ++ggc_stats
->num_rtxs
[(int) code
];
192 ggc_stats
->size_rtxs
[(int) code
] += ggc_get_size (r
);
195 /* ??? If (some of) these are really pass-dependent info, do we
196 have any right poking our noses in? */
200 gt_ggc_m_mem_attrs (MEM_ATTRS (r
));
203 ggc_mark_rtx (JUMP_LABEL (r
));
206 ggc_mark_rtx (LABEL_REFS (r
));
209 ggc_mark_rtx (LABEL_NEXTREF (r
));
210 ggc_mark_rtx (CONTAINING_INSN (r
));
213 ggc_mark_tree (ADDRESSOF_DECL (r
));
216 switch (NOTE_LINE_NUMBER (r
))
218 case NOTE_INSN_RANGE_BEG
:
219 case NOTE_INSN_RANGE_END
:
221 case NOTE_INSN_EXPECTED_VALUE
:
222 ggc_mark_rtx (NOTE_RANGE_INFO (r
));
225 case NOTE_INSN_BLOCK_BEG
:
226 case NOTE_INSN_BLOCK_END
:
227 ggc_mark_tree (NOTE_BLOCK (r
));
239 for (fmt
= GET_RTX_FORMAT (GET_CODE (r
)), i
= 0; *fmt
; ++fmt
, ++i
)
246 if (ggc_test_and_set_mark (exp
))
248 if (next_rtx
== NULL
)
251 ggc_mark_rtx_children (exp
);
255 gt_ggc_m_rtvec_def (XVEC (r
, i
));
260 while ((r
= next_rtx
) != NULL
);
263 /* Various adaptor functions. */
265 gt_ggc_mx_rtx_def (x
)
268 ggc_mark_rtx((rtx
)x
);
271 /* Allocate a block of memory, then clear it. */
273 ggc_alloc_cleared (size
)
276 void *buf
= ggc_alloc (size
);
277 memset (buf
, 0, size
);
281 /* Resize a block of memory, possibly re-allocating it. */
283 ggc_realloc (x
, size
)
291 return ggc_alloc (size
);
293 old_size
= ggc_get_size (x
);
294 if (size
<= old_size
)
297 r
= ggc_alloc (size
);
298 memcpy (r
, x
, old_size
);
302 /* Like ggc_alloc_cleared, but performs a multiplication. */
307 return ggc_alloc_cleared (s1
* s2
);
310 /* Print statistics that are independent of the collector in use. */
311 #define SCALE(x) ((unsigned long) ((x) < 1024*10 \
313 : ((x) < 1024*1024*10 \
315 : (x) / (1024*1024))))
316 #define LABEL(x) ((x) < 1024*10 ? ' ' : ((x) < 1024*1024*10 ? 'k' : 'M'))
319 ggc_print_common_statistics (stream
, stats
)
321 ggc_statistics
*stats
;
325 /* Set the pointer so that during collection we will actually gather
329 /* Then do one collection to fill in the statistics. */
332 /* Total the statistics. */
333 for (code
= 0; code
< MAX_TREE_CODES
; ++code
)
335 stats
->total_num_trees
+= stats
->num_trees
[code
];
336 stats
->total_size_trees
+= stats
->size_trees
[code
];
338 for (code
= 0; code
< NUM_RTX_CODE
; ++code
)
340 stats
->total_num_rtxs
+= stats
->num_rtxs
[code
];
341 stats
->total_size_rtxs
+= stats
->size_rtxs
[code
];
344 /* Print the statistics for trees. */
345 fprintf (stream
, "\n%-17s%10s %16s %10s\n", "Tree",
346 "Number", "Bytes", "% Total");
347 for (code
= 0; code
< MAX_TREE_CODES
; ++code
)
348 if (ggc_stats
->num_trees
[code
])
350 fprintf (stream
, "%-17s%10u%16ld%c %10.3f\n",
351 tree_code_name
[code
],
352 ggc_stats
->num_trees
[code
],
353 SCALE (ggc_stats
->size_trees
[code
]),
354 LABEL (ggc_stats
->size_trees
[code
]),
355 (100 * ((double) ggc_stats
->size_trees
[code
])
356 / ggc_stats
->total_size_trees
));
359 "%-17s%10u%16ld%c\n", "Total",
360 ggc_stats
->total_num_trees
,
361 SCALE (ggc_stats
->total_size_trees
),
362 LABEL (ggc_stats
->total_size_trees
));
364 /* Print the statistics for RTL. */
365 fprintf (stream
, "\n%-17s%10s %16s %10s\n", "RTX",
366 "Number", "Bytes", "% Total");
367 for (code
= 0; code
< NUM_RTX_CODE
; ++code
)
368 if (ggc_stats
->num_rtxs
[code
])
370 fprintf (stream
, "%-17s%10u%16ld%c %10.3f\n",
372 ggc_stats
->num_rtxs
[code
],
373 SCALE (ggc_stats
->size_rtxs
[code
]),
374 LABEL (ggc_stats
->size_rtxs
[code
]),
375 (100 * ((double) ggc_stats
->size_rtxs
[code
])
376 / ggc_stats
->total_size_rtxs
));
379 "%-17s%10u%16ld%c\n", "Total",
380 ggc_stats
->total_num_rtxs
,
381 SCALE (ggc_stats
->total_size_rtxs
),
382 LABEL (ggc_stats
->total_size_rtxs
));
384 /* Don't gather statistics any more. */