mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-11 19:07:19 +08:00
Makefile.in (GGC, GGC_LIB): New.
* 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. From-SVN: r29106
This commit is contained in:
parent
482cbc74aa
commit
0a25f1f5e2
@ -1,3 +1,20 @@
|
||||
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.
|
||||
|
||||
Sat Sep 4 13:11:01 1999 Bernd Schmidt <bernds@cygnus.co.uk>
|
||||
|
||||
Change obstack memory management and varasm constant pool handling so
|
||||
|
@ -316,6 +316,12 @@ CLIB=
|
||||
# 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@
|
||||
@ -572,7 +578,7 @@ HOST_LIBS = $(USE_HOST_OBSTACK) $(USE_HOST_ALLOCA) $(USE_HOST_MALLOC) \
|
||||
$(HOST_INTLLIBS) $(USE_HOST_VFPRINTF) $(USE_HOST_DOPRINT) \
|
||||
$(HOST_CLIB)
|
||||
|
||||
HOST_RTL = $(HOST_PREFIX)rtl.o $(HOST_PREFIX)bitmap.o
|
||||
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
|
||||
@ -1424,6 +1430,11 @@ gencheck.o : gencheck.c tree.def $(CONFIG_H) hconfig.h system.h
|
||||
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
|
||||
|
@ -93,17 +93,17 @@ static int no_line_numbers;
|
||||
|
||||
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 */
|
||||
{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
|
||||
|
58
gcc/ggc-none.c
Normal file
58
gcc/ggc-none.c
Normal file
@ -0,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;
|
||||
}
|
714
gcc/ggc-simple.c
Normal file
714
gcc/ggc-simple.c
Normal file
@ -0,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
|
72
gcc/ggc.h
Normal file
72
gcc/ggc.h
Normal file
@ -0,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 *));
|
@ -102,13 +102,13 @@ typedef struct rtx_def
|
||||
{
|
||||
#ifdef ONLY_INT_FIELDS
|
||||
#ifdef CODE_FIELD_BUG
|
||||
unsigned int code : 16;
|
||||
unsigned int code : 15;
|
||||
#else
|
||||
unsigned short code;
|
||||
#endif
|
||||
#else
|
||||
/* The kind of expression this is. */
|
||||
enum rtx_code code : 16;
|
||||
enum rtx_code code : 15;
|
||||
#endif
|
||||
/* The kind of value the expression has. */
|
||||
#ifdef ONLY_INT_FIELDS
|
||||
@ -171,6 +171,10 @@ typedef struct rtx_def
|
||||
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. */
|
||||
@ -202,6 +206,7 @@ typedef struct rtx_def
|
||||
|
||||
typedef struct rtvec_def{
|
||||
int num_elem; /* number of elements */
|
||||
int gc_mark;
|
||||
struct rtx_def *elem[1];
|
||||
} *rtvec;
|
||||
|
||||
|
17
gcc/toplev.c
17
gcc/toplev.c
@ -54,6 +54,7 @@ Boston, MA 02111-1307, USA. */
|
||||
#include "expr.h"
|
||||
#include "basic-block.h"
|
||||
#include "intl.h"
|
||||
#include "ggc.h"
|
||||
|
||||
#ifdef DWARF_DEBUGGING_INFO
|
||||
#include "dwarfout.h"
|
||||
@ -1350,6 +1351,8 @@ int stack_reg_time;
|
||||
int final_time;
|
||||
int symout_time;
|
||||
int dump_time;
|
||||
int gc_time;
|
||||
int all_time;
|
||||
|
||||
/* Return time used so far, in microseconds. */
|
||||
|
||||
@ -1429,8 +1432,9 @@ print_time (str, total)
|
||||
int total;
|
||||
{
|
||||
fprintf (stderr,
|
||||
"time in %s: %d.%06d\n",
|
||||
str, total / 1000000, total % 1000000);
|
||||
"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. */
|
||||
@ -3446,9 +3450,11 @@ compile_file (name)
|
||||
|
||||
if (! quiet_flag)
|
||||
{
|
||||
fprintf (stderr,"\n");
|
||||
print_time ("parse", parse_time);
|
||||
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);
|
||||
@ -3473,6 +3479,7 @@ compile_file (name)
|
||||
print_time ("varconst", varconst_time);
|
||||
print_time ("symout", symout_time);
|
||||
print_time ("dump", dump_time);
|
||||
print_time ("gc", gc_time);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3772,7 +3779,7 @@ rest_of_compilation (decl)
|
||||
/* 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 (); */
|
||||
/* fixup_stack_slots (); */
|
||||
|
||||
/* Find all the EH handlers. */
|
||||
find_exception_handler_labels ();
|
||||
|
@ -194,7 +194,10 @@ struct tree_common
|
||||
unsigned lang_flag_4 : 1;
|
||||
unsigned lang_flag_5 : 1;
|
||||
unsigned lang_flag_6 : 1;
|
||||
/* There is room for three more flags. */
|
||||
|
||||
unsigned gc_mark : 1;
|
||||
|
||||
/* There is room for two more flags. */
|
||||
};
|
||||
|
||||
/* The following table lists the uses of each of the above flags and
|
||||
|
Loading…
Reference in New Issue
Block a user