OSDN Git Service

Alex Samuel <samuel@codesourcery.com>
[pf3gnuchains/gcc-fork.git] / gcc / ggc-simple.c
1 /* Simple garbage collection for the GNU compiler.
2    Copyright (C) 1998 Free Software Foundation, Inc.
3
4    This file is part of GNU CC.
5
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)
9    any later version.
10
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.
15
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.  */
20
21 #include "config.h"
22 #include "system.h"
23 #include "rtl.h"
24 #include "tree.h"
25 #include "ggc.h"
26 #include "flags.h"
27 #include "varray.h"
28 #include "hash.h"
29
30 /* Debugging flags.  */
31
32 /* Zap memory before freeing to catch dangling pointers.  */
33 #define GGC_POISON
34
35 /* Log alloc and release.  Don't enable this unless you want a
36    really really lot of data.  */
37 #undef GGC_DUMP
38
39 /* Some magic tags for strings and anonymous memory, hoping to catch
40    certain errors wrt marking memory.  */
41
42 #define IS_MARKED(X)            ((X) & 1)
43 #define IGNORE_MARK(X)          ((X) & -2)
44
45 #define GGC_STRING_MAGIC        ((unsigned int)0xa1b2c3d4)
46 #define GGC_STRING_MAGIC_MARK   ((unsigned int)0xa1b2c3d4 | 1)
47
48 #define GGC_ANY_MAGIC           ((unsigned int)0xa9bacbdc)
49 #define GGC_ANY_MAGIC_MARK      ((unsigned int)0xa9bacbdc | 1)
50
51 /* Global lists of roots, rtxs, and trees.  */
52
53 struct ggc_rtx
54 {
55   struct ggc_rtx *chain;
56   struct rtx_def rtx;
57 };
58
59 struct ggc_rtvec
60 {
61   struct ggc_rtvec *chain;
62   struct rtvec_def vec;
63 };
64
65 struct ggc_tree
66 {
67   struct ggc_tree *chain;
68   union tree_node tree;
69 };
70
71 struct ggc_string
72 {
73   struct ggc_string *chain;
74   unsigned int magic_mark;
75   char string[1];
76 };
77
78 /* A generic allocation, with an external mark bit.  */
79
80 struct ggc_any
81 {
82   struct ggc_any *chain;
83   unsigned int magic_mark;
84
85   /* Make sure the data is reasonably aligned.  */
86   union {
87     char c;
88     HOST_WIDE_INT i;
89     long double d;
90   } u;
91 };
92
93 struct ggc_status
94 {
95   struct ggc_status *next;
96   struct ggc_rtx *rtxs;
97   struct ggc_rtvec *vecs;
98   struct ggc_tree *trees;
99   struct ggc_string *strings;
100   struct ggc_any *anys;
101   size_t bytes_alloced_since_gc;
102 };
103
104 /* A chain of GGC contexts.  The currently active context is at the
105    front of the chain.  */
106 static struct ggc_status *ggc_chain;
107
108 /* Some statistics.  */
109
110 static int n_rtxs_collected;
111 static int n_vecs_collected;
112 static int n_trees_collected;
113 static int n_strings_collected;
114 static int n_anys_collected;
115 extern int gc_time;
116
117 #ifdef GGC_DUMP
118 static FILE *dump;
119 #endif
120
121 /* Local function prototypes.  */
122
123 static void ggc_free_rtx PROTO ((struct ggc_rtx *r));
124 static void ggc_free_rtvec PROTO ((struct ggc_rtvec *v));
125 static void ggc_free_tree PROTO ((struct ggc_tree *t));
126 static void ggc_free_string PROTO ((struct ggc_string *s));
127 static void ggc_free_any PROTO ((struct ggc_any *a));
128
129 /* Called once to initialize the garbage collector.  */
130
131 void 
132 init_ggc PROTO ((void))
133 {
134   /* Initialize the global context.  */
135   ggc_push_context ();
136
137 #ifdef GGC_DUMP
138   dump = fopen ("zgcdump", "w");
139   setlinebuf (dump);
140 #endif
141 }
142
143 /* Start a new GGC context.  Memory allocated in previous contexts
144    will not be collected while the new context is active.  */
145
146 void
147 ggc_push_context PROTO ((void))
148 {
149   struct ggc_status *gs = (struct ggc_status *) xcalloc (1, sizeof (*gs));
150   gs->next = ggc_chain;
151   ggc_chain = gs;
152 }
153
154 /* Finish a GC context.  Any uncollected memory in the new context
155    will be merged with the old context.  */
156
157 void 
158 ggc_pop_context PROTO ((void))
159 {
160   struct ggc_rtx *r;
161   struct ggc_rtvec *v;
162   struct ggc_tree *t;
163   struct ggc_string *s;
164   struct ggc_status *gs;
165
166   gs = ggc_chain;
167
168   r = gs->rtxs;
169   if (r)
170     {
171       while (r->chain)
172         r = r->chain;
173       r->chain = gs->next->rtxs;
174       gs->next->rtxs = gs->rtxs;
175     }
176       
177   v = gs->vecs;
178   if (v)
179     {
180       while (v->chain)
181         v = v->chain;
182       v->chain = gs->next->vecs;
183       gs->next->vecs = gs->vecs;
184     }
185
186   t = gs->trees;
187   if (t)
188     {
189       while (t->chain)
190         t = t->chain;
191       t->chain = gs->next->trees;
192       gs->next->trees = gs->trees;
193     }
194
195   s = gs->strings;
196   if (s)
197     {
198       while (s->chain)
199         s = s->chain;
200       s->chain = gs->next->strings;
201       gs->next->strings = gs->strings;
202     }
203
204   ggc_chain = gs->next;
205   free (gs);
206 }
207
208 /* These allocators are dreadfully simple, with no caching whatsoever so
209    that Purify-like tools that do allocation versioning can catch errors.
210    This collector is never going to go fast anyway.  */
211
212 rtx
213 ggc_alloc_rtx (nslots)
214      int nslots;
215 {
216   struct ggc_rtx *n;
217   int size = sizeof(*n) + (nslots-1) * sizeof(rtunion);
218
219   n = (struct ggc_rtx *) xcalloc (1, size);
220   n->chain = ggc_chain->rtxs;
221   ggc_chain->rtxs = n;
222
223 #ifdef GGC_DUMP
224   fprintf (dump, "alloc rtx %p\n", &n->rtx);
225 #endif
226
227   ggc_chain->bytes_alloced_since_gc += size;
228
229   return &n->rtx;
230 }
231
232 rtvec
233 ggc_alloc_rtvec (nelt)
234      int nelt;
235 {
236   struct ggc_rtvec *v;
237   int size = sizeof (*v) + (nelt - 1) * sizeof (rtx);
238
239   v = (struct ggc_rtvec *) xcalloc (1, size);
240   v->chain = ggc_chain->vecs;
241   ggc_chain->vecs = v;
242
243 #ifdef GGC_DUMP
244   fprintf(dump, "alloc vec %p\n", &v->vec);
245 #endif
246
247   ggc_chain->bytes_alloced_since_gc += size;
248
249   return &v->vec;
250 }
251
252 tree
253 ggc_alloc_tree (length)
254      int length;
255 {
256   struct ggc_tree *n;
257   int size = sizeof(*n) - sizeof(n->tree) + length;
258
259   n = (struct ggc_tree *) xcalloc (1, size);
260   n->chain = ggc_chain->trees;
261   ggc_chain->trees = n;
262
263 #ifdef GGC_DUMP
264   fprintf(dump, "alloc tree %p\n", &n->tree);
265 #endif
266
267   ggc_chain->bytes_alloced_since_gc += size;
268
269   return &n->tree;
270 }
271
272 char *
273 ggc_alloc_string (contents, length)
274      const char *contents;
275      int length;
276 {
277   struct ggc_string *s;
278   int size;
279
280   if (length < 0)
281     {
282       if (contents == NULL)
283         return NULL;
284       length = strlen (contents);
285     }
286
287   size = (s->string - (char *)s) + length + 1;
288   s = (struct ggc_string *) xmalloc (size);
289   s->chain = ggc_chain->strings;
290   s->magic_mark = GGC_STRING_MAGIC;
291   ggc_chain->strings = s;
292
293   if (contents)
294     memcpy (s->string, contents, length);
295   s->string[length] = 0;
296
297 #ifdef GGC_DUMP
298   fprintf(dump, "alloc string %p\n", &s->string);
299 #endif
300
301   ggc_chain->bytes_alloced_since_gc += size;
302
303   return s->string;
304 }
305
306 /* Like xmalloc, but allocates GC-able memory.  */
307
308 void *
309 ggc_alloc (bytes)
310      size_t bytes;
311 {
312   struct ggc_any *a;
313
314   if (bytes == 0)
315     bytes = 1;
316   bytes += (&((struct ggc_any *) 0)->u.c - (char *) 0);
317
318   a = (struct ggc_any *) xmalloc (bytes);
319   a->chain = ggc_chain->anys;
320   a->magic_mark = GGC_ANY_MAGIC;
321   ggc_chain->anys = a;
322
323   ggc_chain->bytes_alloced_since_gc += bytes;
324
325   return &a->u;
326 }
327
328 /* Freeing a bit of rtl is as simple as calling free.  */
329
330 static inline void
331 ggc_free_rtx (r)
332      struct ggc_rtx *r;
333 {
334 #ifdef GGC_DUMP
335   fprintf (dump, "collect rtx %p\n", &r->rtx);
336 #endif
337 #ifdef GGC_POISON
338   memset (r, 0xAA, sizeof(*r) + ((GET_RTX_LENGTH (r->rtx.code) -1)
339                                  * sizeof(rtunion)));
340 #endif
341
342   free (r);
343 }
344
345 /* Freeing an rtvec is as simple as calling free.  */
346
347 static inline void
348 ggc_free_rtvec (v)
349      struct ggc_rtvec *v;
350 {
351 #ifdef GGC_DUMP
352   fprintf(dump, "collect vec %p\n", &v->vec);
353 #endif
354 #ifdef GGC_POISON
355   memset (v, 0xBB, sizeof (*v) + ((GET_NUM_ELEM (&v->vec) - 1)
356                                   * sizeof (rtunion)));
357 #endif
358
359   free (v);
360 }
361
362 /* Freeing a tree node is almost, but not quite, as simple as calling free.
363    Mostly we need to let the language clean up its lang_specific bits.  */
364
365 static inline void
366 ggc_free_tree (t)
367      struct ggc_tree *t;
368 {
369 #ifdef GGC_DUMP
370   fprintf (dump, "collect tree %p\n", &t->tree);
371 #endif
372 #ifdef GGC_POISON
373   memset(&t->tree.common, 0xCC, sizeof(t->tree.common));
374 #endif
375
376   free (t);
377 }
378
379 /* Freeing a string is as simple as calling free.  */
380
381 static inline void
382 ggc_free_string (s)
383      struct ggc_string *s;
384 {
385 #ifdef GGC_DUMP
386   fprintf(dump, "collect string %p\n", s->string);
387 #endif
388 #ifdef GGC_POISON
389   s->magic_mark = 0xDDDDDDDD;
390   s->string[0] = 0xDD;
391 #endif
392
393   free (s);
394 }
395
396 /* Freeing anonymous memory is as simple as calling free.  */
397
398 static inline void
399 ggc_free_any (a)
400      struct ggc_any *a;
401 {
402 #ifdef GGC_DUMP
403   fprintf(dump, "collect mem %p\n", &a->u);
404 #endif
405 #ifdef GGC_POISON
406   a->magic_mark = 0xEEEEEEEE;
407 #endif
408
409   free (a);
410 }
411
412 /* Mark a node.  */
413
414 int
415 ggc_set_mark_rtx (r)
416      rtx r;
417 {
418   int marked = r->gc_mark;
419   if (! marked)
420     r->gc_mark = 1;
421   return marked;
422 }
423
424 int
425 ggc_set_mark_rtvec (v)
426      rtvec v;
427 {
428   int marked = v->gc_mark;
429   if (! marked)
430     v->gc_mark = 1;
431   return marked;
432 }
433
434 int
435 ggc_set_mark_tree (t)
436      tree t;
437 {
438   int marked = t->common.gc_mark;
439   if (! marked)
440     t->common.gc_mark = 1;
441   return marked;
442 }
443
444 void
445 ggc_mark_string (s)
446      char *s;
447 {
448   const ptrdiff_t d = (((struct ggc_string *) 0)->string - (char *) 0);
449   struct ggc_string *gs;
450
451   if (s == NULL)
452     return;
453
454   gs = (struct ggc_string *)(s - d);
455   if (IGNORE_MARK (gs->magic_mark) != GGC_STRING_MAGIC)
456     return;   /* abort? */
457   gs->magic_mark = GGC_STRING_MAGIC_MARK;
458 }
459
460 /* Mark P, allocated with ggc_alloc.  */
461
462 void
463 ggc_mark (p)
464      void *p;
465 {
466   const ptrdiff_t d = (&((struct ggc_any *) 0)->u.c - (char *) 0);
467   struct ggc_any *a;
468
469   if (p == NULL)
470     return;
471
472   a = (struct ggc_any *) (((char*) p) - d);
473   if (IGNORE_MARK (a->magic_mark) != GGC_ANY_MAGIC)
474     abort ();
475   a->magic_mark = GGC_ANY_MAGIC_MARK;
476 }
477
478 /* The top level mark-and-sweep routine.  */
479
480 void
481 ggc_collect ()
482 {
483   struct ggc_rtx *r, **rp;
484   struct ggc_rtvec *v, **vp;
485   struct ggc_tree *t, **tp;
486   struct ggc_string *s, **sp;
487   struct ggc_root *x;
488   struct ggc_status *gs;
489   struct ggc_any *a, **ap;
490   int time, n_rtxs, n_trees, n_vecs, n_strings, n_anys;
491
492 #ifndef ENABLE_CHECKING
493   /* See if it's even worth our while.  */
494   if (ggc_chain->bytes_alloced_since_gc < 64*1024)
495     return;
496 #endif
497
498   if (!quiet_flag)
499     fputs (" {GC ", stderr);
500
501   time = get_run_time ();
502
503   /* Clean out all of the GC marks.  */
504   for (gs = ggc_chain; gs; gs = gs->next)
505     {
506       for (r = gs->rtxs; r != NULL; r = r->chain)
507         r->rtx.gc_mark = 0;
508       for (v = gs->vecs; v != NULL; v = v->chain)
509         v->vec.gc_mark = 0;
510       for (t = gs->trees; t != NULL; t = t->chain)
511         t->tree.common.gc_mark = 0;
512       for (s = gs->strings; s != NULL; s = s->chain)
513         s->magic_mark = GGC_STRING_MAGIC;
514       for (a = gs->anys; a != NULL; a = a->chain)
515         a->magic_mark = GGC_ANY_MAGIC;
516     }
517
518   /* Mark through all the roots.  */
519   for (x = roots; x != NULL; x = x->next)
520     {
521       char *elt = x->base;
522       int s = x->size, n = x->nelt;
523       void (*cb) PROTO ((void *)) = x->cb;
524       int i;
525
526       for (i = 0; i < n; ++i, elt += s)
527         (*cb)(elt);
528     }
529
530   /* Sweep the resulting dead nodes.  */
531
532   /* The RTXs.  */
533
534   rp = &ggc_chain->rtxs;
535   r = ggc_chain->rtxs;
536   n_rtxs = 0;
537   while (r != NULL)
538     {
539       struct ggc_rtx *chain = r->chain;
540       if (!r->rtx.gc_mark)
541         {
542           ggc_free_rtx (r);
543           *rp = chain;
544           n_rtxs++;
545         }
546       else
547         rp = &r->chain;
548       r = chain;
549     }
550   *rp = NULL;
551   n_rtxs_collected += n_rtxs;
552
553   /* The vectors.  */
554
555   vp = &ggc_chain->vecs;
556   v = ggc_chain->vecs;
557   n_vecs = 0;
558   while (v != NULL)
559     {
560       struct ggc_rtvec *chain = v->chain;
561       if (!v->vec.gc_mark)
562         {
563           ggc_free_rtvec (v);
564           *vp = chain;
565           n_vecs++;
566         }
567       else
568         vp = &v->chain;
569       v = chain;
570     }
571   *vp = NULL;
572   n_vecs_collected += n_vecs;
573
574   /* The trees.  */
575
576   tp = &ggc_chain->trees;
577   t = ggc_chain->trees;
578   n_trees = 0;
579   while (t != NULL)
580     {
581       struct ggc_tree *chain = t->chain;
582       if (!t->tree.common.gc_mark)
583         {
584           ggc_free_tree (t);
585           *tp = chain;
586           n_trees++;
587         }
588       else
589         tp = &t->chain;
590       t = chain;
591     }
592   *tp = NULL;
593   n_trees_collected += n_trees;
594
595   /* The strings.  */
596
597   sp = &ggc_chain->strings;
598   s = ggc_chain->strings;
599   n_strings = 0;
600   while (s != NULL)
601     {
602       struct ggc_string *chain = s->chain;
603       if (! IS_MARKED (s->magic_mark))
604         {
605           ggc_free_string (s);
606           *sp = chain;
607           n_strings++;
608         }
609       else
610         sp = &s->chain;
611       s = chain;
612     }
613   *sp = NULL;
614   n_strings_collected += n_strings;
615
616   /* The generic data.  */
617
618   ap = &ggc_chain->anys;
619   a = ggc_chain->anys;
620   n_anys = 0;
621   while (a != NULL)
622     {
623       struct ggc_any *chain = a->chain;
624       if (! IS_MARKED (a->magic_mark))
625         {
626           ggc_free_any (a);
627           *ap = chain;
628           n_anys++;
629         }
630       else
631         ap = &a->chain;
632       a = chain;
633     }
634   n_anys_collected += n_anys;
635
636   ggc_chain->bytes_alloced_since_gc = 0;
637
638   time = get_run_time () - time;
639   gc_time += time;
640
641   if (!quiet_flag)
642     {
643       time = (time + 500) / 1000;
644       fprintf (stderr, "%dr,%dv,%dt,%ds,%da %d.%03d}", n_rtxs, n_vecs, 
645                n_trees, n_strings, n_anys, time / 1000, time % 1000);
646     }
647 }
648
649 #if 0
650 /* GDB really should have a memory search function.  Since this is just
651    for initial debugging, I won't even pretend to get the __data_start
652    to work on any but alpha-dec-linux-gnu.  */
653 static void **
654 search_data(void **start, void *target)
655 {
656   extern void *__data_start[];
657   void **_end = (void **)sbrk(0);
658
659   if (start == NULL)
660     start = __data_start;
661   while (start < _end)
662     {
663       if (*start == target)
664         return start;
665       start++;
666     }
667   return NULL;
668 }
669 #endif