This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PATCH to include GC files
- To: gcc-patches at gcc dot gnu dot org
- Subject: PATCH to include GC files
- From: Mark Mitchell <mark at codesourcery dot com>
- Date: Sat, 04 Sep 1999 11:32:50 -0700
- Organization: CodeSourcery, LLC
This patch just adds the `ggc' files to the mainline, and adds
appropriate Makefile targets/dependencies. They're not yet linked in
to anything, although my next patch will link them in to the C++
front-end.
--
Mark Mitchell mark@codesourcery.com
CodeSourcery, LLC http://www.codesourcery.com
Sat Sep 4 11:19:52 1999 Richard Henderson <rth@cygnus.com>
* Makefile.in (GGC, GGC_LIB): New.
(HOST_RTL): Include ggc-none.o.
(ggc-simple.o): New target.
(ggc-none.o): Likewise.
* tree.h (tree_common): Add gc_mark.
* rtl.h (struct rtx_def): Steal a bit from code to make gc_mark.
(struct rtvec_def): Add gc_mark.
* emit-rtl.c (global_rtl): Update static initializers to contain
enough initializers.
* ggc.h, ggc-none.c, ggc-simple.c: New files.
* toplev.c (gc_time): New variable.
(all_time): New variable.
(compile_file): Print gc time.
(print_time): Calculate percentage of the whole.
Index: Makefile.in
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/Makefile.in,v
retrieving revision 1.286
diff -c -p -r1.286 Makefile.in
*** Makefile.in 1999/09/03 19:13:34 1.286
--- Makefile.in 1999/09/04 18:19:18
*************** CLIB=
*** 316,321 ****
--- 316,327 ----
# system library.
OBSTACK=obstack.o
+ # The GC method to be used on this system.
+ GGC=ggc-simple.o
+
+ # If a supplementary library is being used for the GC.
+ GGC_LIB=
+
# Configure will set these if you need vfprintf and possibly _doprnt support.
VFPRINTF=@vfprintf@
DOPRINT=@doprint@
*************** HOST_LIBS = $(USE_HOST_OBSTACK) $(USE_HO
*** 572,578 ****
$(HOST_INTLLIBS) $(USE_HOST_VFPRINTF) $(USE_HOST_DOPRINT) \
$(HOST_CLIB)
! HOST_RTL = $(HOST_PREFIX)rtl.o $(HOST_PREFIX)bitmap.o
HOST_RTLANAL = $(HOST_PREFIX)rtlanal.o
HOST_PRINT = $(HOST_PREFIX)print-rtl.o
HOST_ERRORS = $(HOST_PREFIX)errors.o
--- 578,584 ----
$(HOST_INTLLIBS) $(USE_HOST_VFPRINTF) $(USE_HOST_DOPRINT) \
$(HOST_CLIB)
! HOST_RTL = $(HOST_PREFIX)rtl.o $(HOST_PREFIX)bitmap.o $(HOST_PREFIX)ggc-none.o
HOST_RTLANAL = $(HOST_PREFIX)rtlanal.o
HOST_PRINT = $(HOST_PREFIX)print-rtl.o
HOST_ERRORS = $(HOST_PREFIX)errors.o
*************** gencheck.o : gencheck.c tree.def $(CONFI
*** 1424,1429 ****
--- 1430,1440 ----
dumpvers: dumpvers.c
version.o: version.c
+
+ ggc-simple.o: ggc-simple.c $(CONFIG_H) $(RTL_BASE_H) $(TREE_H) flags.h ggc.h
+
+ ggc-none.o: ggc-none.c $(CONFIG_H) $(RTL_BASE_H) ggc.h
+
obstack.o: $(srcdir)/../libiberty/obstack.c $(CONFIG_H)
rm -f obstack.c
$(LN_S) $(srcdir)/../libiberty/obstack.c obstack.c
Index: emit-rtl.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/emit-rtl.c,v
retrieving revision 1.76
diff -c -p -r1.76 emit-rtl.c
*** emit-rtl.c 1999/09/02 01:22:31 1.76
--- emit-rtl.c 1999/09/04 18:19:26
*************** static int no_line_numbers;
*** 93,109 ****
struct _global_rtl global_rtl =
{
! {PC, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* pc_rtx */
! {CC0, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* cc0_rtx */
! {REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* stack_pointer_rtx */
! {REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* frame_pointer_rtx */
! {REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* hard_frame_pointer_rtx */
! {REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* arg_pointer_rtx */
! {REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* virtual_incoming_args_rtx */
! {REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* virtual_stack_vars_rtx */
! {REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* virtual_stack_dynamic_rtx */
! {REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* virtual_outgoing_args_rtx */
! {REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* virtual_cfa_rtx */
};
/* We record floating-point CONST_DOUBLEs in each floating-point mode for
--- 93,109 ----
struct _global_rtl global_rtl =
{
! {PC, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* pc_rtx */
! {CC0, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* cc0_rtx */
! {REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* stack_pointer_rtx */
! {REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* frame_pointer_rtx */
! {REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* hard_frame_pointer_rtx */
! {REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* arg_pointer_rtx */
! {REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* virtual_incoming_args_rtx */
! {REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* virtual_stack_vars_rtx */
! {REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* virtual_stack_dynamic_rtx */
! {REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* virtual_outgoing_args_rtx */
! {REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* virtual_cfa_rtx */
};
/* We record floating-point CONST_DOUBLEs in each floating-point mode for
Index: ggc-none.c
===================================================================
RCS file: ggc-none.c
diff -N ggc-none.c
*** /dev/null Sat Dec 5 20:30:03 1998
--- ggc-none.c Sat Sep 4 11:19:26 1999
***************
*** 0 ****
--- 1,58 ----
+ /* Null garbage collection for the GNU compiler.
+ Copyright (C) 1998 Free Software Foundation, Inc.
+
+ This file is part of GNU CC.
+
+ GNU CC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU CC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU CC; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+ /* This version is used by the gen* programs, where we don't really
+ need GC at all. This prevents problems with pulling in all the
+ tree stuff. */
+
+ /* We are used by gengenrtl, before genrtl.h exists. But we don't
+ need it either. */
+ #define NO_GENRTL_H
+
+ #include "config.h"
+ #include "system.h"
+ #include "rtl.h"
+ #include "ggc.h"
+
+ rtx
+ ggc_alloc_rtx (nslots)
+ int nslots;
+ {
+ int size = sizeof(struct rtx_def) + (nslots - 1) * sizeof(rtunion);
+ rtx n;
+
+ n = (rtx) xmalloc (size);
+ bzero ((char *) n, size);
+
+ return n;
+ }
+
+ rtvec
+ ggc_alloc_rtvec (nelt)
+ int nelt;
+ {
+ int size = sizeof (struct rtvec_def) + (nelt - 1) * sizeof (rtunion);
+ rtvec v;
+
+ v = (rtvec) xmalloc (size);
+ bzero ((char *) v, size);
+
+ return v;
+ }
Index: ggc-simple.c
===================================================================
RCS file: ggc-simple.c
diff -N ggc-simple.c
*** /dev/null Sat Dec 5 20:30:03 1998
--- ggc-simple.c Sat Sep 4 11:19:27 1999
***************
*** 0 ****
--- 1,714 ----
+ /* Simple garbage collection for the GNU compiler.
+ Copyright (C) 1998 Free Software Foundation, Inc.
+
+ This file is part of GNU CC.
+
+ GNU CC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU CC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU CC; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+ #include "config.h"
+ #include "system.h"
+ #include "rtl.h"
+ #include "tree.h"
+ #include "ggc.h"
+ #include "flags.h"
+
+ /* Debugging flags. */
+ #undef GGC_DUMP
+ #define GGC_POISON
+
+ /* Global lists of roots, rtxs, and trees. */
+
+ struct ggc_root
+ {
+ struct ggc_root *next;
+ void *base;
+ int nelt;
+ int size;
+ void (*cb)(void *);
+ };
+
+ static struct ggc_root *roots;
+
+ struct ggc_rtx
+ {
+ struct ggc_rtx *chain;
+ struct rtx_def rtx;
+ };
+
+ static struct ggc_rtx *rtxs;
+
+ struct ggc_rtvec
+ {
+ struct ggc_rtvec *chain;
+ struct rtvec_def vec;
+ };
+
+ static struct ggc_rtvec *vecs;
+
+ struct ggc_tree
+ {
+ struct ggc_tree *chain;
+ union tree_node tree;
+ };
+
+ static struct ggc_tree *trees;
+
+ struct ggc_string
+ {
+ struct ggc_string *chain;
+ int magic_mark;
+ char string[1];
+ };
+
+ #define GGC_STRING_MAGIC ((unsigned int)0xa1b2c3d4)
+
+ static struct ggc_string *strings;
+
+ /* Some statistics. */
+
+ static int n_rtxs_collected;
+ static int n_vecs_collected;
+ static int n_trees_collected;
+ static int n_strings_collected;
+ static int bytes_alloced_since_gc;
+ extern int gc_time;
+
+ #ifdef GGC_DUMP
+ static FILE *dump;
+ #endif
+
+ /* Local function prototypes. */
+
+ static void ggc_free_rtx PROTO ((struct ggc_rtx *r));
+ static void ggc_free_tree PROTO ((struct ggc_tree *t));
+ static void ggc_mark_rtx_ptr PROTO ((void *elt));
+ static void ggc_mark_tree_ptr PROTO ((void *elt));
+
+ /* These allocators are dreadfully simple, with no caching whatsoever so
+ that Purify-like tools that do allocation versioning can catch errors.
+ This collector is never going to go fast anyway. */
+
+ rtx
+ ggc_alloc_rtx (nslots)
+ int nslots;
+ {
+ struct ggc_rtx *n;
+ int size = sizeof(*n) + (nslots-1) * sizeof(rtunion);
+
+ n = (struct ggc_rtx *) xmalloc (size);
+ bzero ((char *) n, size);
+ n->chain = rtxs;
+ rtxs = n;
+
+ #ifdef GGC_DUMP
+ fprintf (dump, "alloc rtx %p\n", &n->rtx);
+ #endif
+
+ bytes_alloced_since_gc += size;
+
+ return &n->rtx;
+ }
+
+ rtvec
+ ggc_alloc_rtvec (nelt)
+ int nelt;
+ {
+ struct ggc_rtvec *v;
+ int size = sizeof (*v) + (nelt - 1) * sizeof (rtunion);
+
+ v = (struct ggc_rtvec *) xmalloc (size);
+ bzero ((char *) v, size);
+ v->chain = vecs;
+ vecs = v;
+
+ #ifdef GGC_DUMP
+ fprintf(dump, "alloc vec %p\n", &v->vec);
+ #endif
+
+ bytes_alloced_since_gc += size;
+
+ return &v->vec;
+ }
+
+ tree
+ ggc_alloc_tree (length)
+ int length;
+ {
+ struct ggc_tree *n;
+ int size = sizeof(*n) - sizeof(n->tree) + length;
+
+ n = (struct ggc_tree *) xmalloc (size);
+ bzero ((char *) n, size);
+ n->chain = trees;
+ trees = n;
+
+ #ifdef GGC_DUMP
+ fprintf(dump, "alloc tree %p\n", &n->tree);
+ #endif
+
+ bytes_alloced_since_gc += size;
+
+ return &n->tree;
+ }
+
+ char *
+ ggc_alloc_string (contents, length)
+ const char *contents;
+ int length;
+ {
+ struct ggc_string *s;
+ int size;
+
+ if (length < 0)
+ {
+ if (contents == NULL)
+ return NULL;
+ length = strlen (contents);
+ }
+
+ size = (s->string - (char *)s) + length + 1;
+ s = (struct ggc_string *) xmalloc(size);
+ s->chain = strings;
+ s->magic_mark = GGC_STRING_MAGIC;
+ if (contents)
+ bcopy (contents, s->string, length);
+ s->string[length] = 0;
+ strings = s;
+
+ #ifdef GGC_DUMP
+ fprintf(dump, "alloc string %p\n", &n->tree);
+ #endif
+
+ bytes_alloced_since_gc += size;
+
+ return s->string;
+ }
+
+
+ /* Freeing a bit of rtl isn't quite as simple as calling free, there are
+ a few associated bits that might need freeing as well. */
+
+ static void
+ ggc_free_rtx (r)
+ struct ggc_rtx *r;
+ {
+ #ifdef GGC_DUMP
+ fprintf (dump, "collect rtx %p\n", &r->rtx);
+ #endif
+ #ifdef GGC_POISON
+ memset (r, 0xAA, sizeof(*r));
+ #endif
+
+ free (r);
+ }
+
+ /* Freeing an rtvec is as simple as calling free. */
+
+ static void
+ ggc_free_rtvec (v)
+ struct ggc_rtvec *v;
+ {
+ #ifdef GGC_DUMP
+ fprintf(dump, "collect vec %p\n", &v->vec);
+ #endif
+ #ifdef GGC_POISON
+ memset (v, 0xBB, sizeof (*v) + ((GET_NUM_ELEM (&v->vec) - 1)
+ * sizeof (rtunion)));
+ #endif
+
+ free (v);
+ }
+
+ /* Freeing a tree node is almost, but not quite, as simple as calling free.
+ Mostly we need to let the language clean up its lang_specific bits. */
+
+ static void
+ ggc_free_tree (t)
+ struct ggc_tree *t;
+ {
+ switch (TREE_CODE_CLASS (TREE_CODE (&t->tree)))
+ {
+ case 'd': /* A decl node. */
+ case 't': /* A type node. */
+ lang_cleanup_tree (&t->tree);
+ break;
+ }
+
+ #ifdef GGC_DUMP
+ fprintf (dump, "collect tree %p\n", &t->tree);
+ #endif
+ #ifdef GGC_POISON
+ memset(&t->tree.common, 0xCC, sizeof(t->tree.common));
+ #endif
+
+ free (t);
+ }
+
+ /* Freeing a string is as simple as calling free. */
+
+ static void
+ ggc_free_string (s)
+ struct ggc_string *s;
+ {
+ #ifdef GGC_DUMP
+ fprintf(dump, "collect string %p\n", s->string);
+ #endif
+ #ifdef GGC_POISON
+ s->magic_mark = 0xDDDDDDDD;
+ s->string[0] = 0xDD;
+ #endif
+
+ free (s);
+ }
+
+ /* Mark a node. */
+
+ void
+ ggc_mark_rtx (r)
+ rtx r;
+ {
+ const char *fmt;
+ int i;
+
+ if (r == NULL_RTX || r->gc_mark)
+ return;
+ r->gc_mark = 1;
+
+ /* ??? If (some of) these are really pass-dependant info, do we have
+ any right poking our noses in? */
+ switch (GET_CODE (r))
+ {
+ case JUMP_INSN:
+ ggc_mark_rtx (JUMP_LABEL (r));
+ break;
+ case CODE_LABEL:
+ ggc_mark_rtx (LABEL_REFS (r));
+ break;
+ case LABEL_REF:
+ ggc_mark_rtx (LABEL_NEXTREF (r));
+ ggc_mark_rtx (CONTAINING_INSN (r));
+ break;
+ case ADDRESSOF:
+ ggc_mark_tree (ADDRESSOF_DECL (r));
+ break;
+ case CONST_DOUBLE:
+ ggc_mark_rtx (CONST_DOUBLE_CHAIN (r));
+ break;
+
+ default:
+ break;
+ }
+
+ for (fmt = GET_RTX_FORMAT (GET_CODE (r)), i = 0; *fmt ; ++fmt, ++i)
+ {
+ switch (*fmt)
+ {
+ case 'e': case 'u':
+ ggc_mark_rtx (XEXP (r, i));
+ break;
+ case 'V': case 'E':
+ ggc_mark_rtvec (XVEC (r, i));
+ break;
+ case 'S': case 's':
+ ggc_mark_string (XSTR (r, i));
+ break;
+ }
+ }
+ }
+
+ void
+ ggc_mark_rtvec (v)
+ rtvec v;
+ {
+ int i;
+
+ if (v == NULL || v->gc_mark)
+ return;
+ v->gc_mark = 1;
+
+ i = GET_NUM_ELEM (v);
+ while (--i >= 0)
+ ggc_mark_rtx (RTVEC_ELT (v, i));
+ }
+
+ void
+ ggc_mark_tree (t)
+ tree t;
+ {
+ if (t == NULL_TREE || t->common.gc_mark)
+ return;
+ t->common.gc_mark = 1;
+
+ /* Bits from common. */
+ ggc_mark_tree (TREE_TYPE (t));
+ ggc_mark_tree (TREE_CHAIN (t));
+
+ /* Some nodes require special handling. */
+ switch (TREE_CODE (t))
+ {
+ case TREE_LIST:
+ ggc_mark_tree (TREE_PURPOSE (t));
+ ggc_mark_tree (TREE_VALUE (t));
+ return;
+
+ case TREE_VEC:
+ {
+ int i = TREE_VEC_LENGTH (t);
+ while (--i >= 0)
+ ggc_mark_tree (TREE_VEC_ELT (t, i));
+ return;
+ }
+
+ case SAVE_EXPR:
+ ggc_mark_tree (TREE_OPERAND (t, 0));
+ ggc_mark_tree (SAVE_EXPR_CONTEXT (t));
+ ggc_mark_rtx (SAVE_EXPR_RTL (t));
+ return;
+
+ case RTL_EXPR:
+ ggc_mark_rtx (RTL_EXPR_SEQUENCE (t));
+ ggc_mark_rtx (RTL_EXPR_RTL (t));
+ return;
+
+ case CALL_EXPR:
+ ggc_mark_tree (TREE_OPERAND (t, 0));
+ ggc_mark_tree (TREE_OPERAND (t, 1));
+ ggc_mark_rtx (CALL_EXPR_RTL (t));
+ return;
+
+ case COMPLEX_CST:
+ ggc_mark_tree (TREE_REALPART (t));
+ ggc_mark_tree (TREE_IMAGPART (t));
+ break;
+
+ case STRING_CST:
+ ggc_mark_string (TREE_STRING_POINTER (t));
+ break;
+
+ case PARM_DECL:
+ ggc_mark_rtx (DECL_INCOMING_RTL (t));
+ break;
+
+ case IDENTIFIER_NODE:
+ ggc_mark_string (IDENTIFIER_POINTER (t));
+ lang_mark_tree (t);
+ return;
+
+ default:
+ break;
+ }
+
+ /* But in general we can handle them by class. */
+ switch (TREE_CODE_CLASS (TREE_CODE (t)))
+ {
+ case 'd': /* A decl node. */
+ ggc_mark_tree (DECL_SIZE (t));
+ ggc_mark_tree (DECL_NAME (t));
+ ggc_mark_tree (DECL_CONTEXT (t));
+ ggc_mark_tree (DECL_ARGUMENTS (t));
+ ggc_mark_tree (DECL_RESULT (t));
+ ggc_mark_tree (DECL_INITIAL (t));
+ ggc_mark_tree (DECL_ABSTRACT_ORIGIN (t));
+ ggc_mark_tree (DECL_ASSEMBLER_NAME (t));
+ ggc_mark_tree (DECL_SECTION_NAME (t));
+ ggc_mark_tree (DECL_MACHINE_ATTRIBUTES (t));
+ ggc_mark_rtx (DECL_RTL (t));
+ ggc_mark_tree (DECL_VINDEX (t));
+ lang_mark_tree (t);
+ break;
+
+ case 't': /* A type node. */
+ ggc_mark_tree (TYPE_SIZE (t));
+ ggc_mark_tree (TYPE_SIZE_UNIT (t));
+ ggc_mark_tree (TYPE_ATTRIBUTES (t));
+ ggc_mark_tree (TYPE_VALUES (t));
+ ggc_mark_tree (TYPE_POINTER_TO (t));
+ ggc_mark_tree (TYPE_REFERENCE_TO (t));
+ ggc_mark_tree (TYPE_NAME (t));
+ ggc_mark_tree (TYPE_MIN_VALUE (t));
+ ggc_mark_tree (TYPE_MAX_VALUE (t));
+ ggc_mark_tree (TYPE_NEXT_VARIANT (t));
+ ggc_mark_tree (TYPE_MAIN_VARIANT (t));
+ ggc_mark_tree (TYPE_BINFO (t));
+ ggc_mark_tree (TYPE_NONCOPIED_PARTS (t));
+ ggc_mark_tree (TYPE_CONTEXT (t));
+ lang_mark_tree (t);
+ break;
+
+ case 'b': /* A lexical block. */
+ ggc_mark_tree (BLOCK_VARS (t));
+ ggc_mark_tree (BLOCK_TYPE_TAGS (t));
+ ggc_mark_tree (BLOCK_SUBBLOCKS (t));
+ ggc_mark_tree (BLOCK_SUPERCONTEXT (t));
+ ggc_mark_tree (BLOCK_ABSTRACT_ORIGIN (t));
+ ggc_mark_rtx (BLOCK_END_NOTE (t));
+ break;
+
+ case 'c': /* A constant. */
+ ggc_mark_rtx (TREE_CST_RTL (t));
+ break;
+
+ case 'r': case '<': case '1':
+ case '2': case 'e': case 's': /* Expressions. */
+ {
+ int i = tree_code_length[TREE_CODE (t)];
+ while (--i >= 0)
+ ggc_mark_tree (TREE_OPERAND (t, i));
+ break;
+ }
+ }
+ }
+
+ void
+ ggc_mark_string (s)
+ char *s;
+ {
+ unsigned int *magic = (unsigned int *)s - 1;
+
+ if (s == NULL)
+ return;
+
+ if ((*magic & ~(unsigned)1) != GGC_STRING_MAGIC)
+ return; /* abort? */
+ *magic = GGC_STRING_MAGIC | 1;
+ }
+
+ /* The top level mark-and-sweep routine. */
+
+ void
+ ggc_collect ()
+ {
+ struct ggc_rtx *r, **rp;
+ struct ggc_rtvec *v, **vp;
+ struct ggc_tree *t, **tp;
+ struct ggc_string *s, **sp;
+ struct ggc_root *x;
+ int time, n_rtxs, n_trees, n_vecs, n_strings;
+
+ #ifndef ENABLE_CHECKING
+ /* See if it's even worth our while. */
+ if (bytes_alloced_since_gc < 64*1024)
+ return;
+ #endif
+
+ if (!quiet_flag)
+ fputs (" {GC ", stderr);
+
+ time = get_run_time ();
+
+ /* Clean out all of the GC marks. */
+ for (r = rtxs; r != NULL; r = r->chain)
+ r->rtx.gc_mark = 0;
+ for (v = vecs; v != NULL; v = v->chain)
+ v->vec.gc_mark = 0;
+ for (t = trees; t != NULL; t = t->chain)
+ t->tree.common.gc_mark = 0;
+ for (s = strings; s != NULL; s = s->chain)
+ s->magic_mark = GGC_STRING_MAGIC;
+
+ /* Mark through all the roots. */
+ for (x = roots; x != NULL; x = x->next)
+ {
+ char *elt = x->base;
+ int s = x->size, n = x->nelt;
+ void (*cb)(void *) = x->cb;
+ int i;
+
+ for (i = 0; i < n; ++i, elt += s)
+ (*cb)(elt);
+ }
+
+ /* Sweep the resulting dead nodes. */
+ rp = &rtxs, r = rtxs, n_rtxs = 0;
+ while (r != NULL)
+ {
+ struct ggc_rtx *chain = r->chain;
+ if (!r->rtx.gc_mark)
+ {
+ ggc_free_rtx (r);
+ *rp = chain;
+ n_rtxs++;
+ }
+ else
+ rp = &r->chain;
+ r = chain;
+ }
+ *rp = NULL;
+ n_rtxs_collected += n_rtxs;
+
+ vp = &vecs, v = vecs, n_vecs = 0;
+ while (v != NULL)
+ {
+ struct ggc_rtvec *chain = v->chain;
+ if (!v->vec.gc_mark)
+ {
+ ggc_free_rtvec (v);
+ *vp = chain;
+ n_vecs++;
+ }
+ else
+ vp = &v->chain;
+ v = chain;
+ }
+ *vp = NULL;
+ n_vecs_collected += n_vecs;
+
+ tp = &trees, t = trees, n_trees = 0;
+ while (t != NULL)
+ {
+ struct ggc_tree *chain = t->chain;
+ if (!t->tree.common.gc_mark)
+ {
+ ggc_free_tree (t);
+ *tp = chain;
+ n_trees++;
+ }
+ else
+ tp = &t->chain;
+ t = chain;
+ }
+ *tp = NULL;
+ n_trees_collected += n_trees;
+
+ sp = &strings, s = strings, n_strings = 0;
+ while (s != NULL)
+ {
+ struct ggc_string *chain = s->chain;
+ if (!(s->magic_mark & 1))
+ {
+ ggc_free_string (s);
+ *sp = chain;
+ n_strings++;
+ }
+ else
+ sp = &s->chain;
+ s = chain;
+ }
+ *sp = NULL;
+ n_strings_collected += n_strings;
+
+ gc_time += time = get_run_time () - time;
+
+ if (!quiet_flag)
+ {
+ time = (time + 500) / 1000;
+ fprintf (stderr, "%d,%d,%d,%d %d.%03d}", n_rtxs, n_vecs, n_trees,
+ n_strings, time / 1000, time % 1000);
+ }
+ }
+
+ /* Manipulate global roots that are needed between calls to gc. */
+
+ void
+ ggc_add_root (base, nelt, size, cb)
+ void *base;
+ int nelt, size;
+ void (*cb) PROTO ((void *));
+ {
+ struct ggc_root *x = (struct ggc_root *) xmalloc (sizeof(*x));
+
+ x->next = roots;
+ x->base = base;
+ x->nelt = nelt;
+ x->size = size;
+ x->cb = cb;
+
+ roots = x;
+ }
+
+ void
+ ggc_add_rtx_root (base, nelt)
+ rtx *base;
+ int nelt;
+ {
+ ggc_add_root (base, nelt, sizeof(rtx), ggc_mark_rtx_ptr);
+ }
+
+ void
+ ggc_add_tree_root (base, nelt)
+ tree *base;
+ int nelt;
+ {
+ ggc_add_root (base, nelt, sizeof(tree), ggc_mark_tree_ptr);
+ }
+
+ void
+ ggc_del_root (base)
+ void *base;
+ {
+ struct ggc_root *x, **p;
+
+ p = &roots, x = roots;
+ while (x)
+ {
+ if (x->base == base)
+ {
+ *p = x->next;
+ free (x);
+ return;
+ }
+ p = &x->next;
+ x = x->next;
+ }
+
+ abort();
+ }
+
+ static void
+ ggc_mark_rtx_ptr (elt)
+ void *elt;
+ {
+ ggc_mark_rtx (*(rtx *)elt);
+ }
+
+ static void
+ ggc_mark_tree_ptr (elt)
+ void *elt;
+ {
+ ggc_mark_tree (*(tree *)elt);
+ }
+
+ #ifdef GGC_DUMP
+ /* Don't enable this unless you want a really really lot of data. */
+ static void __attribute__((constructor))
+ init(void)
+ {
+ dump = fopen ("zgcdump", "w");
+ setlinebuf (dump);
+ }
+ #endif
+
+ #if 0
+ /* GDB really should have a memory search function. Since this is just
+ for initial debugging, I won't even pretend to get the __data_start
+ to work on any but alpha-dec-linux-gnu. */
+ static void **
+ search_data(void **start, void *target)
+ {
+ extern void *__data_start[];
+ void **_end = (void **)sbrk(0);
+
+ if (start == NULL)
+ start = __data_start;
+ while (start < _end)
+ {
+ if (*start == target)
+ return start;
+ start++;
+ }
+ return NULL;
+ }
+ #endif
Index: ggc.h
===================================================================
RCS file: ggc.h
diff -N ggc.h
*** /dev/null Sat Dec 5 20:30:03 1998
--- ggc.h Sat Sep 4 11:19:27 1999
***************
*** 0 ****
--- 1,72 ----
+ /* Garbage collection for the GNU compiler.
+ Copyright (C) 1998 Free Software Foundation, Inc.
+
+ This file is part of GNU CC.
+
+ GNU CC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU CC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU CC; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+ #include "gansidecl.h"
+
+ /* Symbols are marked with `ggc' for `gcc gc' so as not to interfere with
+ an external gc library that might be linked in. */
+
+ /* Startup */
+
+ extern void init_ggc PROTO ((void));
+
+ /* Allocation. */
+
+ struct rtx_def *ggc_alloc_rtx PROTO ((int nslots));
+ struct rtvec_def *ggc_alloc_rtvec PROTO ((int nelt));
+ union tree_node *ggc_alloc_tree PROTO ((int length));
+ char *ggc_alloc_string PROTO ((const char *contents, int length));
+
+ /* Invoke the collector. This is really just a hint, but in the case of
+ the simple collector, the only time it will happen. */
+
+ void ggc_collect PROTO ((void));
+
+ /* Manipulate global roots that are needed between calls to gc. */
+ void ggc_add_root PROTO ((void *base, int nelt, int size,
+ void (*)(void *)));
+ void ggc_add_rtx_root PROTO ((struct rtx_def **, int nelt));
+ void ggc_add_tree_root PROTO ((union tree_node **, int nelt));
+ void ggc_del_root PROTO ((void *base));
+
+ /* Mark nodes from the gc_add_root callback. */
+ void ggc_mark_rtx PROTO ((struct rtx_def *));
+ void ggc_mark_rtvec PROTO ((struct rtvec_def *));
+ void ggc_mark_tree PROTO ((union tree_node *));
+ void ggc_mark_string PROTO ((char *));
+
+ /* Callbacks to the languages. */
+
+ /* This is the language's opportunity to mark nodes held through
+ the lang_specific hooks in the tree. */
+ void lang_mark_tree PROTO ((union tree_node *));
+
+ /* And similarly to free that data when the tree node is released. */
+ void lang_cleanup_tree PROTO ((union tree_node *));
+
+ /* Mark functions for various structs scattered about. */
+
+ void mark_temp_slot PROTO ((void *));
+ void mark_function_chain PROTO ((void *));
+ void mark_eh_state PROTO ((void *));
+ void mark_stmt_state PROTO ((void *));
+ void mark_emit_state PROTO ((void *));
+ void mark_varasm_state PROTO ((void *));
+ void mark_optab PROTO ((void *));
Index: rtl.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/rtl.h,v
retrieving revision 1.128
diff -c -p -r1.128 rtl.h
*** rtl.h 1999/09/03 22:54:55 1.128
--- rtl.h 1999/09/04 18:19:28
*************** typedef struct rtx_def
*** 100,112 ****
{
#ifdef ONLY_INT_FIELDS
#ifdef CODE_FIELD_BUG
! unsigned int code : 16;
#else
unsigned short code;
#endif
#else
/* The kind of expression this is. */
! enum rtx_code code : 16;
#endif
/* The kind of value the expression has. */
#ifdef ONLY_INT_FIELDS
--- 100,112 ----
{
#ifdef ONLY_INT_FIELDS
#ifdef CODE_FIELD_BUG
! unsigned int code : 15;
#else
unsigned short code;
#endif
#else
/* The kind of expression this is. */
! enum rtx_code code : 15;
#endif
/* The kind of value the expression has. */
#ifdef ONLY_INT_FIELDS
*************** typedef struct rtx_def
*** 169,174 ****
--- 169,178 ----
1 in a MEM if the MEM refers to a scalar, rather than a member of
an aggregate. */
unsigned frame_related : 1;
+
+ /* Used by the garbage collector. */
+ unsigned gc_mark : 1;
+
/* The first element of the operands of this rtx.
The number of operands and their types are controlled
by the `code' field, according to rtl.def. */
*************** typedef struct rtx_def
*** 200,205 ****
--- 204,210 ----
typedef struct rtvec_def{
int num_elem; /* number of elements */
+ int gc_mark;
struct rtx_def *elem[1];
} *rtvec;
Index: toplev.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/toplev.c,v
retrieving revision 1.203
diff -c -p -r1.203 toplev.c
*** toplev.c 1999/09/02 05:42:04 1.203
--- toplev.c 1999/09/04 18:19:32
*************** Boston, MA 02111-1307, USA. */
*** 54,59 ****
--- 54,60 ----
#include "expr.h"
#include "basic-block.h"
#include "intl.h"
+ #include "ggc.h"
#ifdef DWARF_DEBUGGING_INFO
#include "dwarfout.h"
*************** int stack_reg_time;
*** 1350,1355 ****
--- 1351,1358 ----
int final_time;
int symout_time;
int dump_time;
+ int gc_time;
+ int all_time;
/* Return time used so far, in microseconds. */
*************** print_time (str, total)
*** 1429,1436 ****
int total;
{
fprintf (stderr,
! "time in %s: %d.%06d\n",
! str, total / 1000000, total % 1000000);
}
/* Count an error or warning. Return 1 if the message should be printed. */
--- 1432,1440 ----
int total;
{
fprintf (stderr,
! "time in %s: %d.%06d (%.0f%%)\n",
! str, total / 1000000, total % 1000000,
! (double)total / (double)all_time * 100.0);
}
/* Count an error or warning. Return 1 if the message should be printed. */
*************** compile_file (name)
*** 3446,3454 ****
if (! quiet_flag)
{
fprintf (stderr,"\n");
- print_time ("parse", parse_time);
print_time ("integration", integration_time);
print_time ("jump", jump_time);
print_time ("cse", cse_time);
--- 3450,3460 ----
if (! quiet_flag)
{
+ all_time = get_run_time ();
+
fprintf (stderr,"\n");
+ print_time ("parse", parse_time);
print_time ("integration", integration_time);
print_time ("jump", jump_time);
print_time ("cse", cse_time);
*************** compile_file (name)
*** 3473,3478 ****
--- 3479,3485 ----
print_time ("varconst", varconst_time);
print_time ("symout", symout_time);
print_time ("dump", dump_time);
+ print_time ("gc", gc_time);
}
}
*************** rest_of_compilation (decl)
*** 3820,3826 ****
/* See if we have allocated stack slots that are not directly addressable.
If so, scan all the insns and create explicit address computation
for all references to such slots. */
! /* fixup_stack_slots (); */
/* Find all the EH handlers. */
find_exception_handler_labels ();
--- 3827,3833 ----
/* See if we have allocated stack slots that are not directly addressable.
If so, scan all the insns and create explicit address computation
for all references to such slots. */
! /* fixup_stack_slots (); */
/* Find all the EH handlers. */
find_exception_handler_labels ();
Index: tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/tree.h,v
retrieving revision 1.84
diff -c -p -r1.84 tree.h
*** tree.h 1999/08/31 02:15:46 1.84
--- tree.h 1999/09/04 18:19:33
*************** struct tree_common
*** 194,200 ****
unsigned lang_flag_4 : 1;
unsigned lang_flag_5 : 1;
unsigned lang_flag_6 : 1;
! /* There is room for three more flags. */
};
/* The following table lists the uses of each of the above flags and
--- 194,203 ----
unsigned lang_flag_4 : 1;
unsigned lang_flag_5 : 1;
unsigned lang_flag_6 : 1;
!
! unsigned gc_mark : 1;
!
! /* There is room for two more flags. */
};
/* The following table lists the uses of each of the above flags and