1 /* Simple garbage collection for the GNU compiler.
2 Copyright (C) 1998, 1999 Free Software Foundation, Inc.
4 This file is part of GNU CC.
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
30 /* Debugging flags. */
32 /* Zap memory before freeing to catch dangling pointers. */
35 /* Log alloc and release. Don't enable this unless you want a
36 really really lot of data. */
39 /* Some magic tags for strings and anonymous memory, hoping to catch
40 certain errors wrt marking memory. */
42 #define IS_MARKED(X) ((X) & 1)
43 #define IGNORE_MARK(X) ((X) & -2)
45 #define GGC_STRING_MAGIC ((unsigned int)0xa1b2c3d4)
46 #define GGC_STRING_MAGIC_MARK ((unsigned int)0xa1b2c3d4 | 1)
48 #define GGC_ANY_MAGIC ((unsigned int)0xa9bacbdc)
49 #define GGC_ANY_MAGIC_MARK ((unsigned int)0xa9bacbdc | 1)
51 /* Global lists of roots, rtxs, and trees. */
55 struct ggc_rtx *chain;
61 struct ggc_rtvec *chain;
67 struct ggc_tree *chain;
73 struct ggc_string *chain;
74 unsigned int magic_mark;
78 /* A generic allocation, with an external mark bit. */
82 struct ggc_any *chain;
83 unsigned int magic_mark;
85 /* Make sure the data is reasonably aligned. */
89 #ifdef HAVE_LONG_DOUBLE
99 struct ggc_status *next;
100 struct ggc_rtx *rtxs;
101 struct ggc_rtvec *vecs;
102 struct ggc_tree *trees;
103 struct ggc_string *strings;
104 struct ggc_any *anys;
105 size_t bytes_alloced_since_gc;
108 /* A chain of GGC contexts. The currently active context is at the
109 front of the chain. */
110 static struct ggc_status *ggc_chain;
112 /* Some statistics. */
114 static int n_rtxs_collected;
115 static int n_vecs_collected;
116 static int n_trees_collected;
117 static int n_strings_collected;
118 static int n_anys_collected;
125 /* Local function prototypes. */
127 static void ggc_free_rtx PROTO ((struct ggc_rtx *r));
128 static void ggc_free_rtvec PROTO ((struct ggc_rtvec *v));
129 static void ggc_free_tree PROTO ((struct ggc_tree *t));
130 static void ggc_free_string PROTO ((struct ggc_string *s));
131 static void ggc_free_any PROTO ((struct ggc_any *a));
133 /* Called once to initialize the garbage collector. */
136 init_ggc PROTO ((void))
138 /* Initialize the global context. */
142 dump = fopen ("zgcdump", "w");
147 /* Start a new GGC context. Memory allocated in previous contexts
148 will not be collected while the new context is active. */
151 ggc_push_context PROTO ((void))
153 struct ggc_status *gs = (struct ggc_status *) xcalloc (1, sizeof (*gs));
154 gs->next = ggc_chain;
158 /* Finish a GC context. Any uncollected memory in the new context
159 will be merged with the old context. */
162 ggc_pop_context PROTO ((void))
167 struct ggc_string *s;
168 struct ggc_status *gs;
177 r->chain = gs->next->rtxs;
178 gs->next->rtxs = gs->rtxs;
186 v->chain = gs->next->vecs;
187 gs->next->vecs = gs->vecs;
195 t->chain = gs->next->trees;
196 gs->next->trees = gs->trees;
204 s->chain = gs->next->strings;
205 gs->next->strings = gs->strings;
208 gs->next->bytes_alloced_since_gc += gs->bytes_alloced_since_gc;
210 ggc_chain = gs->next;
214 /* These allocators are dreadfully simple, with no caching whatsoever so
215 that Purify-like tools that do allocation versioning can catch errors.
216 This collector is never going to go fast anyway. */
219 ggc_alloc_rtx (nslots)
223 int size = sizeof(*n) + (nslots-1) * sizeof(rtunion);
225 n = (struct ggc_rtx *) xcalloc (1, size);
226 n->chain = ggc_chain->rtxs;
230 fprintf (dump, "alloc rtx %p\n", &n->rtx);
233 ggc_chain->bytes_alloced_since_gc += size;
239 ggc_alloc_rtvec (nelt)
243 int size = sizeof (*v) + (nelt - 1) * sizeof (rtx);
245 v = (struct ggc_rtvec *) xcalloc (1, size);
246 v->chain = ggc_chain->vecs;
250 fprintf(dump, "alloc vec %p\n", &v->vec);
253 ggc_chain->bytes_alloced_since_gc += size;
259 ggc_alloc_tree (length)
263 int size = sizeof(*n) - sizeof(n->tree) + length;
265 n = (struct ggc_tree *) xcalloc (1, size);
266 n->chain = ggc_chain->trees;
267 ggc_chain->trees = n;
270 fprintf(dump, "alloc tree %p\n", &n->tree);
273 ggc_chain->bytes_alloced_since_gc += size;
279 ggc_alloc_string (contents, length)
280 const char *contents;
283 struct ggc_string *s;
288 if (contents == NULL)
290 length = strlen (contents);
293 size = (s->string - (char *)s) + length + 1;
294 s = (struct ggc_string *) xmalloc (size);
295 s->chain = ggc_chain->strings;
296 s->magic_mark = GGC_STRING_MAGIC;
297 ggc_chain->strings = s;
300 memcpy (s->string, contents, length);
301 s->string[length] = 0;
304 fprintf(dump, "alloc string %p\n", &s->string);
307 ggc_chain->bytes_alloced_since_gc += size;
312 /* Like xmalloc, but allocates GC-able memory. */
322 bytes += (&((struct ggc_any *) 0)->u.c - (char *) 0);
324 a = (struct ggc_any *) xmalloc (bytes);
325 a->chain = ggc_chain->anys;
326 a->magic_mark = GGC_ANY_MAGIC;
329 ggc_chain->bytes_alloced_since_gc += bytes;
334 /* Freeing a bit of rtl is as simple as calling free. */
341 fprintf (dump, "collect rtx %p\n", &r->rtx);
344 memset (r, 0xAA, sizeof(*r) + ((GET_RTX_LENGTH (r->rtx.code) -1)
351 /* Freeing an rtvec is as simple as calling free. */
358 fprintf(dump, "collect vec %p\n", &v->vec);
361 memset (v, 0xBB, sizeof (*v) + ((GET_NUM_ELEM (&v->vec) - 1)
362 * sizeof (rtunion)));
368 /* Freeing a tree node is almost, but not quite, as simple as calling free.
369 Mostly we need to let the language clean up its lang_specific bits. */
376 fprintf (dump, "collect tree %p\n", &t->tree);
379 memset(&t->tree.common, 0xCC, sizeof(t->tree.common));
385 /* Freeing a string is as simple as calling free. */
389 struct ggc_string *s;
392 fprintf(dump, "collect string %p\n", s->string);
395 s->magic_mark = 0xDDDDDDDD;
402 /* Freeing anonymous memory is as simple as calling free. */
409 fprintf(dump, "collect mem %p\n", &a->u);
412 a->magic_mark = 0xEEEEEEEE;
424 int marked = r->gc_mark;
431 ggc_set_mark_rtvec (v)
434 int marked = v->gc_mark;
441 ggc_set_mark_tree (t)
444 int marked = t->common.gc_mark;
446 t->common.gc_mark = 1;
454 const ptrdiff_t d = (((struct ggc_string *) 0)->string - (char *) 0);
455 struct ggc_string *gs;
460 gs = (struct ggc_string *)(s - d);
461 if (IGNORE_MARK (gs->magic_mark) != GGC_STRING_MAGIC)
463 gs->magic_mark = GGC_STRING_MAGIC_MARK;
466 /* Mark P, allocated with ggc_alloc. */
472 const ptrdiff_t d = (&((struct ggc_any *) 0)->u.c - (char *) 0);
478 a = (struct ggc_any *) (((char*) p) - d);
479 if (IGNORE_MARK (a->magic_mark) != GGC_ANY_MAGIC)
481 a->magic_mark = GGC_ANY_MAGIC_MARK;
484 /* The top level mark-and-sweep routine. */
489 struct ggc_rtx *r, **rp;
490 struct ggc_rtvec *v, **vp;
491 struct ggc_tree *t, **tp;
492 struct ggc_string *s, **sp;
494 struct ggc_status *gs;
495 struct ggc_any *a, **ap;
496 int time, n_rtxs, n_trees, n_vecs, n_strings, n_anys;
498 #if !defined(ENABLE_CHECKING)
499 /* See if it's even worth our while. */
500 if (ggc_chain->bytes_alloced_since_gc < 4*1024*1024)
505 fputs (" {GC ", stderr);
507 time = get_run_time ();
509 /* Clean out all of the GC marks. */
510 for (gs = ggc_chain; gs; gs = gs->next)
512 for (r = gs->rtxs; r != NULL; r = r->chain)
514 for (v = gs->vecs; v != NULL; v = v->chain)
516 for (t = gs->trees; t != NULL; t = t->chain)
517 t->tree.common.gc_mark = 0;
518 for (s = gs->strings; s != NULL; s = s->chain)
519 s->magic_mark = GGC_STRING_MAGIC;
520 for (a = gs->anys; a != NULL; a = a->chain)
521 a->magic_mark = GGC_ANY_MAGIC;
524 /* Mark through all the roots. */
525 for (x = roots; x != NULL; x = x->next)
528 int s = x->size, n = x->nelt;
529 void (*cb) PROTO ((void *)) = x->cb;
532 for (i = 0; i < n; ++i, elt += s)
536 /* Sweep the resulting dead nodes. */
540 rp = &ggc_chain->rtxs;
545 struct ggc_rtx *chain = r->chain;
557 n_rtxs_collected += n_rtxs;
561 vp = &ggc_chain->vecs;
566 struct ggc_rtvec *chain = v->chain;
578 n_vecs_collected += n_vecs;
582 tp = &ggc_chain->trees;
583 t = ggc_chain->trees;
587 struct ggc_tree *chain = t->chain;
588 if (!t->tree.common.gc_mark)
599 n_trees_collected += n_trees;
603 sp = &ggc_chain->strings;
604 s = ggc_chain->strings;
608 struct ggc_string *chain = s->chain;
609 if (! IS_MARKED (s->magic_mark))
620 n_strings_collected += n_strings;
622 /* The generic data. */
624 ap = &ggc_chain->anys;
629 struct ggc_any *chain = a->chain;
630 if (! IS_MARKED (a->magic_mark))
640 n_anys_collected += n_anys;
642 ggc_chain->bytes_alloced_since_gc = 0;
644 time = get_run_time () - time;
649 time = (time + 500) / 1000;
650 fprintf (stderr, "%dr,%dv,%dt,%ds,%da %d.%03d}", n_rtxs, n_vecs,
651 n_trees, n_strings, n_anys, time / 1000, time % 1000);
656 /* GDB really should have a memory search function. Since this is just
657 for initial debugging, I won't even pretend to get the __data_start
658 to work on any but alpha-dec-linux-gnu. */
660 search_data(void **start, void *target)
662 extern void *__data_start[];
663 void **_end = (void **)sbrk(0);
666 start = __data_start;
669 if (*start == target)