X-Git-Url: https://gcc.gnu.org/git/?a=blobdiff_plain;f=gcc%2Fggc-simple.c;h=488df3a95ab9077ec4f40ad1ab714df39b3bf9a1;hb=25abc0a5efa834a9a39d44f942d3bc3cc5480771;hp=7822bb916f3d90875a97bef7e5603cabee9d56ff;hpb=fba0bfd4546bb2b864a841cf1d43957dbaa38a89;p=gcc.git diff --git a/gcc/ggc-simple.c b/gcc/ggc-simple.c index 7822bb916f3d..488df3a95ab9 100644 --- a/gcc/ggc-simple.c +++ b/gcc/ggc-simple.c @@ -1,46 +1,46 @@ /* Simple garbage collection for the GNU compiler. - Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc. + Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 + Free Software Foundation, Inc. - This file is part of GNU CC. + This file is part of GCC. - 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 + GCC 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. + GCC 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. */ + along with GCC; 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 "coretypes.h" +#include "tm.h" #include "rtl.h" #include "tree.h" #include "tm_p.h" #include "flags.h" #include "varray.h" #include "ggc.h" +#include "toplev.h" #include "timevar.h" +#include "params.h" /* Debugging flags. */ /* Zap memory before freeing to catch dangling pointers. */ -#define GGC_POISON +#undef GGC_POISON /* Collect statistics on how bushy the search tree is. */ #undef GGC_BALANCE -/* Perform collection every time ggc_collect is invoked. Otherwise, - collection is performed only when a significant amount of memory - has been allocated since the last collection. */ -#undef GGC_ALWAYS_COLLECT - /* Always verify that the to-be-marked memory is collectable. */ #undef GGC_ALWAYS_VERIFY @@ -48,13 +48,6 @@ #define GGC_POISON #define GGC_ALWAYS_VERIFY #endif -#ifdef ENABLE_GC_ALWAYS_COLLECT -#define GGC_ALWAYS_COLLECT -#endif - -/* Constants for general use. */ - -char *empty_string; #ifndef HOST_BITS_PER_PTR #define HOST_BITS_PER_PTR HOST_BITS_PER_LONG @@ -93,11 +86,7 @@ struct ggc_mem /* Make sure the data is reasonably aligned. */ union { HOST_WIDEST_INT i; -#ifdef HAVE_LONG_DOUBLE long double d; -#else - double d; -#endif } u; }; @@ -119,37 +108,26 @@ static struct globals int context; } G; -/* Skip garbage collection if the current allocation is not at least - this factor times the allocation at the end of the last collection. - In other words, total allocation must expand by (this factor minus - one) before collection is performed. */ -#define GGC_MIN_EXPAND_FOR_GC (1.3) - -/* Bound `allocated_last_gc' to 4MB, to prevent the memory expansion - test from triggering too often when the heap is small. */ -#define GGC_MIN_LAST_ALLOCATED (4 * 1024 * 1024) - /* Local function prototypes. */ -static void tree_insert PARAMS ((struct ggc_mem *)); -static int tree_lookup PARAMS ((struct ggc_mem *)); -static void clear_marks PARAMS ((struct ggc_mem *)); -static void sweep_objs PARAMS ((struct ggc_mem **)); -static void ggc_pop_context_1 PARAMS ((struct ggc_mem *, int)); +static void tree_insert (struct ggc_mem *); +static int tree_lookup (struct ggc_mem *); +static void clear_marks (struct ggc_mem *); +static void sweep_objs (struct ggc_mem **); +static void ggc_pop_context_1 (struct ggc_mem *, int); /* For use from debugger. */ -extern void debug_ggc_tree PARAMS ((struct ggc_mem *, int)); +extern void debug_ggc_tree (struct ggc_mem *, int); #ifdef GGC_BALANCE -extern void debug_ggc_balance PARAMS ((void)); +extern void debug_ggc_balance (void); #endif -static void tally_leaves PARAMS ((struct ggc_mem *, int, size_t *, size_t *)); +static void tally_leaves (struct ggc_mem *, int, size_t *, size_t *); /* Insert V into the search tree. */ static inline void -tree_insert (v) - struct ggc_mem *v; +tree_insert (struct ggc_mem *v) { size_t v_key = PTR_KEY (v); struct ggc_mem *p, **pp; @@ -165,8 +143,7 @@ tree_insert (v) /* Return true if V is in the tree. */ static inline int -tree_lookup (v) - struct ggc_mem *v; +tree_lookup (struct ggc_mem *v) { size_t v_key = PTR_KEY (v); struct ggc_mem *p = G.root; @@ -185,8 +162,7 @@ tree_lookup (v) /* Alloc SIZE bytes of GC'able memory. If ZERO, clear the memory. */ void * -ggc_alloc (size) - size_t size; +ggc_alloc (size_t size) { struct ggc_mem *x; @@ -211,8 +187,7 @@ ggc_alloc (size) /* Mark a node. */ int -ggc_set_mark (p) - const void *p; +ggc_set_mark (const void *p) { struct ggc_mem *x; @@ -232,36 +207,28 @@ ggc_set_mark (p) return 0; } -/* Mark a node, but check first to see that it's really gc-able memory. */ +/* Return 1 if P has been marked, zero otherwise. */ -void -ggc_mark_if_gcable (p) - const void *p; +int +ggc_marked_p (const void *p) { struct ggc_mem *x; - if (p == NULL) - return; - x = (struct ggc_mem *) ((const char *)p - offsetof (struct ggc_mem, u)); +#ifdef GGC_ALWAYS_VERIFY if (! tree_lookup (x)) - return; - - if (x->mark) - return; + abort (); +#endif - x->mark = 1; - G.allocated += x->size; - G.objects += 1; + return x->mark; } /* Return the size of the gc-able object P. */ size_t -ggc_get_size (p) - const void *p; +ggc_get_size (const void *p) { - struct ggc_mem *x + struct ggc_mem *x = (struct ggc_mem *) ((const char *)p - offsetof (struct ggc_mem, u)); return x->size; } @@ -269,8 +236,7 @@ ggc_get_size (p) /* Unmark all objects. */ static void -clear_marks (x) - struct ggc_mem *x; +clear_marks (struct ggc_mem *x) { x->mark = 0; if (x->sub[0]) @@ -282,8 +248,7 @@ clear_marks (x) /* Free all objects in the current context that are not marked. */ static void -sweep_objs (root) - struct ggc_mem **root; +sweep_objs (struct ggc_mem **root) { struct ggc_mem *x = *root; if (!x) @@ -332,12 +297,18 @@ sweep_objs (root) /* The top level mark-and-sweep routine. */ void -ggc_collect () +ggc_collect (void) { -#ifndef GGC_ALWAYS_COLLECT - if (G.allocated < GGC_MIN_EXPAND_FOR_GC * G.allocated_last_gc) + /* Avoid frequent unnecessary work by skipping collection if the + total allocations haven't expanded much since the last + collection. */ + size_t allocated_last_gc = + MAX (G.allocated_last_gc, (size_t)PARAM_VALUE (GGC_MIN_HEAPSIZE) * 1024); + + size_t min_expand = allocated_last_gc * PARAM_VALUE (GGC_MIN_EXPAND) / 100; + + if (G.allocated < allocated_last_gc + min_expand) return; -#endif #ifdef GGC_BALANCE debug_ggc_balance (); @@ -355,8 +326,6 @@ ggc_collect () sweep_objs (&G.root); G.allocated_last_gc = G.allocated; - if (G.allocated_last_gc < GGC_MIN_LAST_ALLOCATED) - G.allocated_last_gc = GGC_MIN_LAST_ALLOCATED; timevar_pop (TV_GC); @@ -370,20 +339,16 @@ ggc_collect () /* Called once to initialize the garbage collector. */ -void -init_ggc () +void +init_ggc (void) { - G.allocated_last_gc = GGC_MIN_LAST_ALLOCATED; - - empty_string = ggc_alloc_string ("", 0); - ggc_add_string_root (&empty_string, 1); } /* Start a new GGC context. Memory allocated in previous contexts will not be collected while the new context is active. */ void -ggc_push_context () +ggc_push_context (void) { G.context++; @@ -396,8 +361,8 @@ ggc_push_context () /* Finish a GC context. Any uncollected memory in the new context will be merged with the old context. */ -void -ggc_pop_context () +void +ggc_pop_context (void) { G.context--; if (G.root) @@ -405,9 +370,7 @@ ggc_pop_context () } static void -ggc_pop_context_1 (x, c) - struct ggc_mem *x; - int c; +ggc_pop_context_1 (struct ggc_mem *x, int c) { if (x->context > c) x->context = c; @@ -420,9 +383,7 @@ ggc_pop_context_1 (x, c) /* Dump a tree. */ void -debug_ggc_tree (p, indent) - struct ggc_mem *p; - int indent; +debug_ggc_tree (struct ggc_mem *p, int indent) { int i; @@ -437,8 +398,8 @@ debug_ggc_tree (p, indent) for (i = 0; i < indent; ++i) putc (' ', stderr); - fprintf (stderr, "%lx %p\n", (unsigned long)PTR_KEY (p), p); - + fprintf (stderr, "%lx %p\n", (unsigned long)PTR_KEY (p), (void *) p); + if (p->sub[1]) debug_ggc_tree (p->sub[1], indent + 1); } @@ -449,7 +410,7 @@ debug_ggc_tree (p, indent) #include void -debug_ggc_balance () +debug_ggc_balance (void) { size_t nleaf, sumdepth; @@ -467,11 +428,7 @@ debug_ggc_balance () /* Used by debug_ggc_balance, and also by ggc_print_statistics. */ static void -tally_leaves (x, depth, nleaf, sumdepth) - struct ggc_mem *x; - int depth; - size_t *nleaf; - size_t *sumdepth; +tally_leaves (struct ggc_mem *x, int depth, size_t *nleaf, size_t *sumdepth) { if (! x->sub[0] && !x->sub[1]) { @@ -496,14 +453,14 @@ tally_leaves (x, depth, nleaf, sumdepth) /* Report on GC memory usage. */ void -ggc_print_statistics () +ggc_print_statistics (void) { struct ggc_statistics stats; size_t nleaf = 0, sumdepth = 0; /* Clear the statistics. */ memset (&stats, 0, sizeof (stats)); - + /* Make sure collection will really occur. */ G.allocated_last_gc = 0; @@ -515,16 +472,80 @@ ggc_print_statistics () fprintf (stderr, "\n\ Total internal data (bytes)\t%ld%c\n\ -Number of leaves in tree\t%d\n\ +Number of leaves in tree\t%lu\n\ Average leaf depth\t\t%.1f\n", SCALE(G.objects * offsetof (struct ggc_mem, u)), LABEL(G.objects * offsetof (struct ggc_mem, u)), - nleaf, (double)sumdepth / (double)nleaf); + (unsigned long)nleaf, (double)sumdepth / (double)nleaf); /* Report overall memory usage. */ fprintf (stderr, "\n\ -Total objects allocated\t\t%d\n\ +Total objects allocated\t\t%ld\n\ Total memory in GC arena\t%ld%c\n", - G.objects, + (unsigned long)G.objects, SCALE(G.allocated), LABEL(G.allocated)); } + +struct ggc_pch_data * +init_ggc_pch (void) +{ + sorry ("Generating PCH files is not supported when using ggc-simple.c"); + /* It could be supported, but the code is not yet written. */ + return NULL; +} + +void +ggc_pch_count_object (struct ggc_pch_data *d ATTRIBUTE_UNUSED, + void *x ATTRIBUTE_UNUSED, + size_t size ATTRIBUTE_UNUSED) +{ +} + +size_t +ggc_pch_total_size (struct ggc_pch_data *d ATTRIBUTE_UNUSED) +{ + return 0; +} + +void +ggc_pch_this_base (struct ggc_pch_data *d ATTRIBUTE_UNUSED, + void *base ATTRIBUTE_UNUSED) +{ +} + + +char * +ggc_pch_alloc_object (struct ggc_pch_data *d ATTRIBUTE_UNUSED, + void *x ATTRIBUTE_UNUSED, + size_t size ATTRIBUTE_UNUSED) +{ + return NULL; +} + +void +ggc_pch_prepare_write (struct ggc_pch_data *d ATTRIBUTE_UNUSED, + FILE * f ATTRIBUTE_UNUSED) +{ +} + +void +ggc_pch_write_object (struct ggc_pch_data *d ATTRIBUTE_UNUSED, + FILE *f ATTRIBUTE_UNUSED, void *x ATTRIBUTE_UNUSED, + void *newx ATTRIBUTE_UNUSED, + size_t size ATTRIBUTE_UNUSED) +{ +} + +void +ggc_pch_finish (struct ggc_pch_data *d ATTRIBUTE_UNUSED, + FILE *f ATTRIBUTE_UNUSED) +{ +} + +void +ggc_pch_read (FILE *f ATTRIBUTE_UNUSED, void *addr ATTRIBUTE_UNUSED) +{ + /* This should be impossible, since we won't generate any valid PCH + files for this configuration. */ + abort (); +}