Commit b49a6a90 by Alex Samuel Committed by Richard Henderson

Alex Samuel <samuel@codesourcery.com>

        * ggc.h (rtvec_def): Forward declare.
        (tree_node): Likewise.
        (ggc_root): Define.
        (roots): Declare.
        (ggc_set_mark_rtx): Add prototype.
        (ggc_set_mark_rtvec): Likewise.
        (ggc_set_mark_tree): Likewise.
        * ggc-simple.c (ggc_root): Don't define.
        (roots): Don't declare.
        (ggc_mark_rtx): Remove.
        (ggc_mark_rtvec): Likewise.
        (ggc_mark_tree): Likewise.
        (ggc_mark_varray): Likewise.
        (ggc_mark_tree_hash_table_entry): Likewise.
        (ggc_mark_tree_hash_table): Likewise.
        (ggc_set_mart_rtx): New function.
        (ggc_set_mark_rtvec): Likewise.
        (ggc_set_mark_tree): Likewise.
        (ggc_add_root): Remove.
        (ggc_add_rtx_root): Likewise.
        (ggc_remove_tree_root): Likewise.
        (ggc_add_string_root): Likewise.
        (ggc_add_tree_varray_root): Likewise.
        (ggc_add_tree_hash_table_root): Likewise.
        (ggc_del_root): Likewise.
        (ggc_mark_rtx_ptr): Likewise.
        (ggc_mark_tree_ptr): Likewise.
        (ggc_mark_string_ptr): Likewise.
        (ggc_mark_tree_varray_ptr): Likewise.
        (ggc_mark_tree_hash_table_ptr): Likewise.
        * ggc-common.c: New file.
        * Makefile.in (OBJS): Add ggc-common.o.
        (ggc-common.o): List dependencies.

From-SVN: r29281
parent 61efc8c2
Sat Sep 11 12:41:55 1999 Alex Samuel <samuel@codesourcery.com>
* ggc.h (rtvec_def): Forward declare.
(tree_node): Likewise.
(ggc_root): Define.
(roots): Declare.
(ggc_set_mark_rtx): Add prototype.
(ggc_set_mark_rtvec): Likewise.
(ggc_set_mark_tree): Likewise.
* ggc-simple.c (ggc_root): Don't define.
(roots): Don't declare.
(ggc_mark_rtx): Remove.
(ggc_mark_rtvec): Likewise.
(ggc_mark_tree): Likewise.
(ggc_mark_varray): Likewise.
(ggc_mark_tree_hash_table_entry): Likewise.
(ggc_mark_tree_hash_table): Likewise.
(ggc_set_mart_rtx): New function.
(ggc_set_mark_rtvec): Likewise.
(ggc_set_mark_tree): Likewise.
(ggc_add_root): Remove.
(ggc_add_rtx_root): Likewise.
(ggc_remove_tree_root): Likewise.
(ggc_add_string_root): Likewise.
(ggc_add_tree_varray_root): Likewise.
(ggc_add_tree_hash_table_root): Likewise.
(ggc_del_root): Likewise.
(ggc_mark_rtx_ptr): Likewise.
(ggc_mark_tree_ptr): Likewise.
(ggc_mark_string_ptr): Likewise.
(ggc_mark_tree_varray_ptr): Likewise.
(ggc_mark_tree_hash_table_ptr): Likewise.
* ggc-common.c: New file.
* Makefile.in (OBJS): Add ggc-common.o.
(ggc-common.o): List dependencies.
1999-09-10 22:37 -0700 Zack Weinberg <zack@bitmover.com> 1999-09-10 22:37 -0700 Zack Weinberg <zack@bitmover.com>
* cppalloc.c (xstrdup): Use memcpy. * cppalloc.c (xstrdup): Use memcpy.
......
...@@ -675,7 +675,7 @@ OBJS = toplev.o version.o tree.o print-tree.o stor-layout.o fold-const.o \ ...@@ -675,7 +675,7 @@ OBJS = toplev.o version.o tree.o print-tree.o stor-layout.o fold-const.o \
insn-opinit.o insn-recog.o insn-extract.o insn-output.o insn-emit.o lcm.o \ insn-opinit.o insn-recog.o insn-extract.o insn-output.o insn-emit.o lcm.o \
profile.o insn-attrtab.o $(out_object_file) $(EXTRA_OBJS) convert.o \ profile.o insn-attrtab.o $(out_object_file) $(EXTRA_OBJS) convert.o \
mbchar.o dyn-string.o splay-tree.o graph.o sbitmap.o resource.o hash.o \ mbchar.o dyn-string.o splay-tree.o graph.o sbitmap.o resource.o hash.o \
lists.o $(GGC) lists.o ggc-common.o $(GGC)
# GEN files are listed separately, so they can be built before doing parallel # GEN files are listed separately, so they can be built before doing parallel
# makes for cc1 or cc1plus. Otherwise sequent parallel make attempts to load # makes for cc1 or cc1plus. Otherwise sequent parallel make attempts to load
...@@ -1445,6 +1445,9 @@ dumpvers: dumpvers.c ...@@ -1445,6 +1445,9 @@ dumpvers: dumpvers.c
version.o: version.c version.o: version.c
ggc-common.o: ggc-common.c $(CONFIG_H) $(RTL_BASE_H) $(TREE_H) \
flags.h ggc.h varray.h hash.h
ggc-simple.o: ggc-simple.c $(CONFIG_H) $(RTL_BASE_H) $(TREE_H) flags.h \ ggc-simple.o: ggc-simple.c $(CONFIG_H) $(RTL_BASE_H) $(TREE_H) flags.h \
ggc.h varray.h hash.h ggc.h varray.h hash.h
......
/* 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. */
/* Generic garbage collection (GC) functions and data, not specific to
any particular GC implementation. */
#include "config.h"
#include "system.h"
#include "ggc.h"
#include "hash.h"
#include "rtl.h"
#include "tree.h"
#include "varray.h"
/* Maintain global roots that are preserved during GC. */
struct ggc_root *roots;
/* Type-correct function to pass to ggc_add_root. It just forwards
*ELT (which is an rtx) to ggc_mark_tree_varray. */
static void
ggc_mark_rtx_ptr (elt)
void *elt;
{
ggc_mark_rtx (*(rtx *)elt);
}
/* Type-correct function to pass to ggc_add_root. It just forwards
*ELT (which is a tree) to ggc_mark_tree. */
static void
ggc_mark_tree_ptr (elt)
void *elt;
{
ggc_mark_tree (*(tree *)elt);
}
/* Type-correct function to pass to ggc_add_root. It just forwards
ELT (which is really a varray_type *) to ggc_mark_tree_varray. */
static void
ggc_mark_tree_varray_ptr (elt)
void *elt;
{
ggc_mark_tree_varray (*(varray_type *)elt);
}
/* Type-correct function to pass to ggc_add_root. It just forwards
ELT (which is really a struct hash_table **) to
ggc_mark_tree_hash_table. */
static void
ggc_mark_tree_hash_table_ptr (elt)
void *elt;
{
ggc_mark_tree_hash_table (*(struct hash_table **) elt);
}
static void
ggc_mark_string_ptr (elt)
void *elt;
{
ggc_mark_string (*(char **)elt);
}
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);
}
/* Add V (a varray full of trees) to the list of GC roots. */
void
ggc_add_tree_varray_root (base, nelt)
varray_type *base;
int nelt;
{
ggc_add_root (base, nelt, sizeof (varray_type),
ggc_mark_tree_varray_ptr);
}
/* Add HT (a hash-table where ever key is a tree) to the list of GC
roots. */
void
ggc_add_tree_hash_table_root (base, nelt)
struct hash_table **base;
int nelt;
{
ggc_add_root (base, nelt, sizeof (struct hash_table *),
ggc_mark_tree_hash_table_ptr);
}
void
ggc_add_string_root (base, nelt)
char **base;
int nelt;
{
ggc_add_root (base, nelt, sizeof (char *), ggc_mark_string_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();
}
void
ggc_mark_rtx (r)
rtx r;
{
const char *fmt;
int i;
if (r == NULL_RTX || ggc_set_mark_rtx (r))
return;
/* ??? 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;
case NOTE:
switch (NOTE_LINE_NUMBER (r))
{
case NOTE_INSN_RANGE_START:
case NOTE_INSN_RANGE_END:
case NOTE_INSN_LIVE:
ggc_mark_rtx (NOTE_RANGE_INFO (r));
break;
default:
if (NOTE_LINE_NUMBER (r) >= 0)
ggc_mark_string (NOTE_SOURCE_FILE (r));
break;
}
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 || ggc_set_mark_rtvec (v))
return;
i = GET_NUM_ELEM (v);
while (--i >= 0)
ggc_mark_rtx (RTVEC_ELT (v, i));
}
void
ggc_mark_tree (t)
tree t;
{
/* FIXME what if t == NULL_TREE ? */
if (t == NULL || ggc_set_mark_tree (t))
return;
/* 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;
}
case 'x':
lang_mark_tree (t);
break;
}
}
/* Mark all the elements of the varray V, which contains trees. */
void
ggc_mark_tree_varray (v)
varray_type v;
{
int i;
if (v)
for (i = v->num_elements - 1; i >= 0; --i)
ggc_mark_tree (VARRAY_TREE (v, i));
}
/* Mark the hash table-entry HE. It's key field is really a tree. */
static boolean
ggc_mark_tree_hash_table_entry (he, k)
struct hash_entry *he;
hash_table_key k ATTRIBUTE_UNUSED;
{
ggc_mark_tree ((tree) he->key);
return true;
}
/* Mark all the elements of the hash-table H, which contains trees. */
void
ggc_mark_tree_hash_table (ht)
struct hash_table *ht;
{
hash_traverse (ht, ggc_mark_tree_hash_table_entry, /*info=*/0);
}
...@@ -50,17 +50,6 @@ ...@@ -50,17 +50,6 @@
/* Global lists of roots, rtxs, and trees. */ /* Global lists of roots, rtxs, and trees. */
struct ggc_root
{
struct ggc_root *next;
void *base;
int nelt;
int size;
void (*cb) PROTO ((void *));
};
static struct ggc_root *roots;
struct ggc_rtx struct ggc_rtx
{ {
struct ggc_rtx *chain; struct ggc_rtx *chain;
...@@ -137,14 +126,6 @@ static void ggc_free_tree PROTO ((struct ggc_tree *t)); ...@@ -137,14 +126,6 @@ static void ggc_free_tree PROTO ((struct ggc_tree *t));
static void ggc_free_string PROTO ((struct ggc_string *s)); static void ggc_free_string PROTO ((struct ggc_string *s));
static void ggc_free_any PROTO ((struct ggc_any *a)); static void ggc_free_any PROTO ((struct ggc_any *a));
static void ggc_mark_rtx_ptr PROTO ((void *elt));
static void ggc_mark_tree_ptr PROTO ((void *elt));
static void ggc_mark_string_ptr PROTO ((void *elt));
static void ggc_mark_tree_varray_ptr PROTO ((void *elt));
static void ggc_mark_tree_hash_table_ptr PROTO ((void *elt));
static boolean ggc_mark_tree_hash_table_entry PROTO ((struct hash_entry *,
hash_table_key));
/* Called once to initialize the garbage collector. */ /* Called once to initialize the garbage collector. */
void void
...@@ -346,7 +327,7 @@ ggc_alloc (bytes) ...@@ -346,7 +327,7 @@ ggc_alloc (bytes)
/* Freeing a bit of rtl is as simple as calling free. */ /* Freeing a bit of rtl is as simple as calling free. */
static inline void static inline void
ggc_free_rtx (r) ggc_free_rtx (r)
struct ggc_rtx *r; struct ggc_rtx *r;
{ {
...@@ -430,252 +411,34 @@ ggc_free_any (a) ...@@ -430,252 +411,34 @@ ggc_free_any (a)
/* Mark a node. */ /* Mark a node. */
void int
ggc_mark_rtx (r) ggc_set_mark_rtx (r)
rtx r; rtx r;
{ {
const char *fmt; int marked = r->gc_mark;
int i; if (! marked)
r->gc_mark = 1;
if (r == NULL_RTX || r->gc_mark) return marked;
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;
case NOTE:
switch (NOTE_LINE_NUMBER (r))
{
case NOTE_INSN_RANGE_START:
case NOTE_INSN_RANGE_END:
case NOTE_INSN_LIVE:
ggc_mark_rtx (NOTE_RANGE_INFO (r));
break;
default:
if (NOTE_LINE_NUMBER (r) >= 0)
ggc_mark_string (NOTE_SOURCE_FILE (r));
break;
}
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 int
ggc_mark_rtvec (v) ggc_set_mark_rtvec (v)
rtvec v; rtvec v;
{ {
int i; int marked = v->gc_mark;
if (! marked)
if (v == NULL || v->gc_mark) v->gc_mark = 1;
return; return marked;
v->gc_mark = 1;
i = GET_NUM_ELEM (v);
while (--i >= 0)
ggc_mark_rtx (RTVEC_ELT (v, i));
} }
void int
ggc_mark_tree (t) ggc_set_mark_tree (t)
tree t; tree t;
{ {
if (t == NULL_TREE || t->common.gc_mark) int marked = t->common.gc_mark;
return; if (! marked)
t->common.gc_mark = 1; t->common.gc_mark = 1;
return marked;
/* 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;
}
case 'x':
lang_mark_tree (t);
break;
}
}
/* Mark all the elements of the varray V, which contains trees. */
void
ggc_mark_tree_varray (v)
varray_type v;
{
int i;
if (v)
for (i = v->num_elements - 1; i >= 0; --i)
ggc_mark_tree (VARRAY_TREE (v, i));
}
/* Mark the hash table-entry HE. It's key field is really a tree. */
static boolean
ggc_mark_tree_hash_table_entry (he, k)
struct hash_entry *he;
hash_table_key k ATTRIBUTE_UNUSED;
{
ggc_mark_tree ((tree) he->key);
return true;
}
/* Mark all the elements of the hash-table H, which contains trees. */
void
ggc_mark_tree_hash_table (ht)
struct hash_table *ht;
{
hash_traverse (ht, ggc_mark_tree_hash_table_entry, /*info=*/0);
} }
void void
...@@ -883,139 +646,6 @@ ggc_collect () ...@@ -883,139 +646,6 @@ ggc_collect ()
} }
} }
/* 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_add_string_root (base, nelt)
char **base;
int nelt;
{
ggc_add_root (base, nelt, sizeof(char *), ggc_mark_string_ptr);
}
/* Add V (a varray full of trees) to the list of GC roots. */
void
ggc_add_tree_varray_root (base, nelt)
varray_type *base;
int nelt;
{
ggc_add_root (base, nelt, sizeof (varray_type),
ggc_mark_tree_varray_ptr);
}
/* Add HT (a hash-table where ever key is a tree) to the list of GC
roots. */
void
ggc_add_tree_hash_table_root (base, nelt)
struct hash_table **base;
int nelt;
{
ggc_add_root (base, nelt, sizeof (struct hash_table *),
ggc_mark_tree_hash_table_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);
}
/* Type-correct function to pass to ggc_add_root. It just forwards
ELT (which is really a char **) to ggc_mark_string. */
static void
ggc_mark_string_ptr (elt)
void *elt;
{
ggc_mark_string (*(char **)elt);
}
/* Type-correct function to pass to ggc_add_root. It just forwards
ELT (which is really a varray_type *) to ggc_mark_tree_varray. */
static void
ggc_mark_tree_varray_ptr (elt)
void *elt;
{
ggc_mark_tree_varray (*(varray_type *)elt);
}
/* Type-correct function to pass to ggc_add_root. It just forwards
ELT (which is really a struct hash_table **) to
ggc_mark_tree_hash_table. */
static void
ggc_mark_tree_hash_table_ptr (elt)
void *elt;
{
ggc_mark_tree_hash_table (*(struct hash_table **) elt);
}
#if 0 #if 0
/* GDB really should have a memory search function. Since this is just /* 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 for initial debugging, I won't even pretend to get the __data_start
......
...@@ -31,27 +31,63 @@ extern int ggc_p; ...@@ -31,27 +31,63 @@ extern int ggc_p;
compiler. However, rather than force everyone who includes this compiler. However, rather than force everyone who includes this
header to include all the headers in which they are declared, we header to include all the headers in which they are declared, we
just forward-declare them here. */ just forward-declare them here. */
struct label_node;
struct eh_status; struct eh_status;
struct emit_status; struct emit_status;
struct hash_table;
struct label_node;
struct rtvec_def;
struct stmt_status; struct stmt_status;
union tree_node;
struct varasm_status; struct varasm_status;
struct varray_head_tag; struct varray_head_tag;
struct hash_table;
/* Startup */ /* Global roots that are preserved during calls to gc. */
struct ggc_root
{
struct ggc_root *next;
void *base;
int nelt;
int size;
void (*cb) PROTO ((void *));
};
extern struct ggc_root *roots;
/* 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_add_string_root PROTO ((char **, int nelt));
void ggc_add_tree_varray_root PROTO ((struct varray_head_tag **, int nelt));
void ggc_add_tree_hash_table_root PROTO ((struct hash_table **, int nelt));
void ggc_del_root PROTO ((void *base));
/* Mark nodes from the gc_add_root callback. These functions follow
pointers to mark other objects too. */
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_tree_varray PROTO ((struct varray_head_tag *));
void ggc_mark_tree_hash_table PROTO ((struct hash_table *));
void ggc_mark_string PROTO ((char *));
void ggc_mark PROTO ((void *));
/* A GC implementation must provide these functions. */
/* Initialize the garbage collector. */
extern void init_ggc PROTO ((void)); extern void init_ggc PROTO ((void));
/* Start a new GGC context. Memory allocated in previous contexts /* Start a new GGC context. Memory allocated in previous contexts
will not be collected while the new context is active. */ will not be collected while the new context is active. */
extern void ggc_pop_context PROTO ((void)); extern void ggc_pop_context PROTO ((void));
/* Finish a GC context. Any uncollected memory in the new context /* Finish a GC context. Any uncollected memory in the new context
will be merged with the old context. */ will be merged with the old context. */
extern void ggc_push_context PROTO ((void)); extern void ggc_push_context PROTO ((void));
/* Allocation. */ /* Allocation. */
struct rtx_def *ggc_alloc_rtx PROTO ((int nslots)); struct rtx_def *ggc_alloc_rtx PROTO ((int nslots));
struct rtvec_def *ggc_alloc_rtvec PROTO ((int nelt)); struct rtvec_def *ggc_alloc_rtvec PROTO ((int nelt));
union tree_node *ggc_alloc_tree PROTO ((int length)); union tree_node *ggc_alloc_tree PROTO ((int length));
...@@ -60,26 +96,17 @@ void *ggc_alloc PROTO ((size_t)); ...@@ -60,26 +96,17 @@ void *ggc_alloc PROTO ((size_t));
/* Invoke the collector. This is really just a hint, but in the case of /* Invoke the collector. This is really just a hint, but in the case of
the simple collector, the only time it will happen. */ the simple collector, the only time it will happen. */
void ggc_collect PROTO ((void)); void ggc_collect PROTO ((void));
/* Manipulate global roots that are needed between calls to gc. */ /* Actually set the mark on a particular region of memory, but don't
void ggc_add_root PROTO ((void *base, int nelt, int size, void (*)(void *))); follow pointers. These functions are called by ggc_mark_*. They
void ggc_add_rtx_root PROTO ((struct rtx_def **, int nelt)); return zero if the object was not previously marked; they return
void ggc_add_tree_root PROTO ((union tree_node **, int nelt)); non-zero if the object was already marked, or if, for any other
void ggc_add_string_root PROTO ((char **, int nelt)); reason, pointers in this data structure should not be traversed. */
void ggc_add_tree_varray_root PROTO ((struct varray_head_tag **, int nelt)); int ggc_set_mark_rtx PROTO ((struct rtx_def *));
void ggc_add_tree_hash_table_root PROTO ((struct hash_table **, int nelt)); int ggc_set_mark_rtvec PROTO ((struct rtvec_def *));
void ggc_del_root PROTO ((void *base)); int ggc_set_mark_tree PROTO ((union tree_node *));
/* 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_tree_varray PROTO ((struct varray_head_tag *));
void ggc_mark_tree_hash_table PROTO ((struct hash_table *));
void ggc_mark_string PROTO ((char *));
void ggc_mark PROTO ((void *));
/* Callbacks to the languages. */ /* Callbacks to the languages. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment