X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Falloc-pool.c;h=9310f1eb0095690267857b7deffd4cee5cbd0e31;hb=f6e5971197e69aa040ca3ad0dc9e580bf3dcbb89;hp=e247b141f76e360585e42c8ddef1da9a64ce7f9b;hpb=aecda0d63740bf543c769e6fed70a34cc7f052e3;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/alloc-pool.c b/gcc/alloc-pool.c index e247b141f76..9310f1eb009 100644 --- a/gcc/alloc-pool.c +++ b/gcc/alloc-pool.c @@ -1,5 +1,5 @@ /* Functions to support a pool of allocatable objects. - Copyright (C) 1987, 1997, 1998, 1999, 2000, 2001, 2003 + Copyright (C) 1987, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005 Free Software Foundation, Inc. Contributed by Daniel Berlin @@ -17,24 +17,14 @@ for more details. You should have received a copy of the GNU General Public License 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. */ +Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301, USA. */ #include "config.h" #include "system.h" #include "alloc-pool.h" +#include "hashtab.h" -/* Redefine abort to report an internal error w/o coredump, and - reporting the location of the error in the source file. This logic - is duplicated in rtl.h and tree.h because every file that needs the - special abort includes one or both. toplev.h gets too few files, - system.h gets too many. */ - -extern void fancy_abort (const char *, int, const char *) - ATTRIBUTE_NORETURN; -#define abort() fancy_abort (__FILE__, __LINE__, __FUNCTION__) - -#define align_four(x) (((x+3) >> 2) << 2) #define align_eight(x) (((x+7) >> 3) << 3) /* The internal allocation object. */ @@ -54,11 +44,8 @@ typedef struct allocation_object_def the following elements are here. They are never accessed so the allocated object may be even smaller than this structure. */ char *align_p; - double align_d; HOST_WIDEST_INT align_i; -#ifdef HAVE_LONG_DOUBLE long double align_ld; -#endif } u; } allocation_object; @@ -76,6 +63,56 @@ typedef struct allocation_object_def static ALLOC_POOL_ID_TYPE last_id; #endif +#ifdef GATHER_STATISTICS + +/* Store information about each particular alloc_pool. */ +struct alloc_pool_descriptor +{ + const char *name; + int allocated; + int created; + int peak; + int current; +}; + +/* Hashtable mapping alloc_pool names to descriptors. */ +static htab_t alloc_pool_hash; + +/* Hashtable helpers. */ +static hashval_t +hash_descriptor (const void *p) +{ + const struct alloc_pool_descriptor *d = p; + return htab_hash_pointer (d->name); +} +static int +eq_descriptor (const void *p1, const void *p2) +{ + const struct alloc_pool_descriptor *d = p1; + return d->name == p2; +} + +/* For given name, return descriptor, create new if needed. */ +static struct alloc_pool_descriptor * +alloc_pool_descriptor (const char *name) +{ + struct alloc_pool_descriptor **slot; + + if (!alloc_pool_hash) + alloc_pool_hash = htab_create (10, hash_descriptor, eq_descriptor, NULL); + + slot = (struct alloc_pool_descriptor **) + htab_find_slot_with_hash (alloc_pool_hash, name, + htab_hash_pointer (name), + 1); + if (*slot) + return *slot; + *slot = xcalloc (sizeof (**slot), 1); + (*slot)->name = name; + return *slot; +} +#endif + /* Create a pool of things of size SIZE, with NUM in each block we allocate. */ @@ -84,16 +121,18 @@ create_alloc_pool (const char *name, size_t size, size_t num) { alloc_pool pool; size_t pool_size, header_size; +#ifdef GATHER_STATISTICS + struct alloc_pool_descriptor *desc; +#endif - if (!name) - abort (); + gcc_assert (name); /* Make size large enough to store the list header. */ if (size < sizeof (alloc_pool_list)) size = sizeof (alloc_pool_list); /* Now align the size to a multiple of 4. */ - size = align_four (size); + size = align_eight (size); #ifdef ENABLE_CHECKING /* Add the aligned size of ID. */ @@ -101,21 +140,24 @@ create_alloc_pool (const char *name, size_t size, size_t num) #endif /* Um, we can't really allocate 0 elements per block. */ - if (num == 0) - abort (); + gcc_assert (num); /* Find the size of the pool structure, and the name. */ pool_size = sizeof (struct alloc_pool_def); /* and allocate that much memory. */ - pool = (alloc_pool) xmalloc (pool_size); + pool = xmalloc (pool_size); /* Now init the various pieces of our pool structure. */ - pool->name = xstrdup (name); + pool->name = /*xstrdup (name)*/name; +#ifdef GATHER_STATISTICS + desc = alloc_pool_descriptor (name); + desc->created++; +#endif pool->elt_size = size; pool->elts_per_block = num; - /* List header size should be a multiple of 8 */ + /* List header size should be a multiple of 8. */ header_size = align_eight (sizeof (struct alloc_pool_list_def)); pool->block_size = (size * num) + header_size; @@ -143,20 +185,25 @@ void free_alloc_pool (alloc_pool pool) { alloc_pool_list block, next_block; - -#ifdef ENABLE_CHECKING - if (!pool) - abort (); +#ifdef GATHER_STATISTICS + struct alloc_pool_descriptor *desc = alloc_pool_descriptor (pool->name); #endif + gcc_assert (pool); + /* Free each block allocated to the pool. */ for (block = pool->block_list; block != NULL; block = next_block) { next_block = block->next; free (block); +#ifdef GATHER_STATISTICS + desc->current -= pool->block_size; +#endif } - /* Lastly, free the pool and the name. */ - free (pool->name); +#ifdef ENABLE_CHECKING + memset (pool, 0xaf, sizeof (*pool)); +#endif + /* Lastly, free the pool. */ free (pool); } @@ -166,24 +213,31 @@ pool_alloc (alloc_pool pool) { alloc_pool_list header; char *block; +#ifdef GATHER_STATISTICS + struct alloc_pool_descriptor *desc = alloc_pool_descriptor (pool->name); -#ifdef ENABLE_CHECKING - if (!pool) - abort (); + desc->allocated+=pool->elt_size; #endif + gcc_assert (pool); + /* If there are no more free elements, make some more!. */ if (!pool->free_list) { size_t i; alloc_pool_list block_header; - /* Make the block */ - block = (char *) xmalloc (pool->block_size); + /* Make the block. */ + block = XNEWVEC (char, pool->block_size); block_header = (alloc_pool_list) block; block += align_eight (sizeof (struct alloc_pool_list_def)); +#ifdef GATHER_STATISTICS + desc->current += pool->block_size; + if (desc->peak < desc->current) + desc->peak = desc->current; +#endif - /* Throw it on the block list */ + /* Throw it on the block list. */ block_header->next = pool->block_list; pool->block_list = block_header; @@ -224,20 +278,19 @@ pool_free (alloc_pool pool, void *ptr) { alloc_pool_list header; + gcc_assert (ptr); + #ifdef ENABLE_CHECKING - if (!ptr) - abort (); + memset (ptr, 0xaf, pool->elt_size - offsetof (allocation_object, u.data)); /* Check whether the PTR was allocated from POOL. */ - if (pool->id != ALLOCATION_OBJECT_PTR_FROM_USER_PTR (ptr)->id) - abort (); + gcc_assert (pool->id == ALLOCATION_OBJECT_PTR_FROM_USER_PTR (ptr)->id); /* Mark the element to be free. */ ALLOCATION_OBJECT_PTR_FROM_USER_PTR (ptr)->id = 0; #else /* Check if we free more than we allocated, which is Bad (TM). */ - if (pool->elts_free + 1 > pool->elts_allocated) - abort (); + gcc_assert (pool->elts_free < pool->elts_allocated); #endif header = (alloc_pool_list) ptr; @@ -245,3 +298,52 @@ pool_free (alloc_pool pool, void *ptr) pool->free_list = header; pool->elts_free++; } +/* Output per-alloc_pool statistics. */ +#ifdef GATHER_STATISTICS + +/* Used to accumulate statistics about alloc_pool sizes. */ +struct output_info +{ + int count; + int size; +}; + +/* Called via htab_traverse. Output alloc_pool descriptor pointed out by SLOT + and update statistics. */ +static int +print_statistics (void **slot, void *b) +{ + struct alloc_pool_descriptor *d = (struct alloc_pool_descriptor *) *slot; + struct output_info *i = (struct output_info *) b; + + if (d->allocated) + { + fprintf (stderr, "%-21s %6d %10d %10d %10d\n", d->name, + d->created, d->allocated, d->peak, d->current); + i->size += d->allocated; + i->count += d->created; + } + return 1; +} +#endif + +/* Output per-alloc_pool memory usage statistics. */ +void dump_alloc_pool_statistics (void) +{ +#ifdef GATHER_STATISTICS + struct output_info info; + + if (!alloc_pool_hash) + return; + + fprintf (stderr, "\nAlloc-pool Kind Pools Allocated Peak Leak\n"); + fprintf (stderr, "-------------------------------------------------------------\n"); + info.count = 0; + info.size = 0; + htab_traverse (alloc_pool_hash, print_statistics, &info); + fprintf (stderr, "-------------------------------------------------------------\n"); + fprintf (stderr, "%-20s %7d %10d\n", + "Total", info.count, info.size); + fprintf (stderr, "-------------------------------------------------------------\n"); +#endif +}