xref: /dflybsd-src/contrib/gcc-4.7/gcc/alloc-pool.c (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
1*e4b17023SJohn Marino /* Functions to support a pool of allocatable objects.
2*e4b17023SJohn Marino    Copyright (C) 1987, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006,
3*e4b17023SJohn Marino    2007, 2008, 2010  Free Software Foundation, Inc.
4*e4b17023SJohn Marino    Contributed by Daniel Berlin <dan@cgsoftware.com>
5*e4b17023SJohn Marino 
6*e4b17023SJohn Marino This file is part of GCC.
7*e4b17023SJohn Marino 
8*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under
9*e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free
10*e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later
11*e4b17023SJohn Marino version.
12*e4b17023SJohn Marino 
13*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14*e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or
15*e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16*e4b17023SJohn Marino for more details.
17*e4b17023SJohn Marino 
18*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
19*e4b17023SJohn Marino along with GCC; see the file COPYING3.  If not see
20*e4b17023SJohn Marino <http://www.gnu.org/licenses/>.  */
21*e4b17023SJohn Marino 
22*e4b17023SJohn Marino #include "config.h"
23*e4b17023SJohn Marino #include "system.h"
24*e4b17023SJohn Marino #include "alloc-pool.h"
25*e4b17023SJohn Marino #include "hashtab.h"
26*e4b17023SJohn Marino 
27*e4b17023SJohn Marino #define align_eight(x) (((x+7) >> 3) << 3)
28*e4b17023SJohn Marino 
29*e4b17023SJohn Marino /* The internal allocation object.  */
30*e4b17023SJohn Marino typedef struct allocation_object_def
31*e4b17023SJohn Marino {
32*e4b17023SJohn Marino #ifdef ENABLE_CHECKING
33*e4b17023SJohn Marino   /* The ID of alloc pool which the object was allocated from.  */
34*e4b17023SJohn Marino   ALLOC_POOL_ID_TYPE id;
35*e4b17023SJohn Marino #endif
36*e4b17023SJohn Marino 
37*e4b17023SJohn Marino   union
38*e4b17023SJohn Marino     {
39*e4b17023SJohn Marino       /* The data of the object.  */
40*e4b17023SJohn Marino       char data[1];
41*e4b17023SJohn Marino 
42*e4b17023SJohn Marino       /* Because we want any type of data to be well aligned after the ID,
43*e4b17023SJohn Marino 	 the following elements are here.  They are never accessed so
44*e4b17023SJohn Marino 	 the allocated object may be even smaller than this structure.
45*e4b17023SJohn Marino 	 We do not care about alignment for floating-point types.  */
46*e4b17023SJohn Marino       char *align_p;
47*e4b17023SJohn Marino       HOST_WIDEST_INT align_i;
48*e4b17023SJohn Marino     } u;
49*e4b17023SJohn Marino } allocation_object;
50*e4b17023SJohn Marino 
51*e4b17023SJohn Marino /* Convert a pointer to allocation_object from a pointer to user data.  */
52*e4b17023SJohn Marino #define ALLOCATION_OBJECT_PTR_FROM_USER_PTR(X)				\
53*e4b17023SJohn Marino    ((allocation_object *) (((char *) (X))				\
54*e4b17023SJohn Marino 			   - offsetof (allocation_object, u.data)))
55*e4b17023SJohn Marino 
56*e4b17023SJohn Marino /* Convert a pointer to user data from a pointer to allocation_object.  */
57*e4b17023SJohn Marino #define USER_PTR_FROM_ALLOCATION_OBJECT_PTR(X)				\
58*e4b17023SJohn Marino    ((void *) (((allocation_object *) (X))->u.data))
59*e4b17023SJohn Marino 
60*e4b17023SJohn Marino #ifdef ENABLE_CHECKING
61*e4b17023SJohn Marino /* Last used ID.  */
62*e4b17023SJohn Marino static ALLOC_POOL_ID_TYPE last_id;
63*e4b17023SJohn Marino #endif
64*e4b17023SJohn Marino 
65*e4b17023SJohn Marino #ifdef GATHER_STATISTICS
66*e4b17023SJohn Marino 
67*e4b17023SJohn Marino /* Store information about each particular alloc_pool.  Note that this
68*e4b17023SJohn Marino    will underestimate the amount the amount of storage used by a small amount:
69*e4b17023SJohn Marino    1) The overhead in a pool is not accounted for.
70*e4b17023SJohn Marino    2) The unallocated elements in a block are not accounted for.  Note
71*e4b17023SJohn Marino    that this can at worst case be one element smaller that the block
72*e4b17023SJohn Marino    size for that pool.  */
73*e4b17023SJohn Marino struct alloc_pool_descriptor
74*e4b17023SJohn Marino {
75*e4b17023SJohn Marino   const char *name;
76*e4b17023SJohn Marino   /* Number of pools allocated.  */
77*e4b17023SJohn Marino   unsigned long created;
78*e4b17023SJohn Marino   /* Gross allocated storage.  */
79*e4b17023SJohn Marino   unsigned long allocated;
80*e4b17023SJohn Marino   /* Amount of currently active storage. */
81*e4b17023SJohn Marino   unsigned long current;
82*e4b17023SJohn Marino   /* Peak amount of storage used.  */
83*e4b17023SJohn Marino   unsigned long peak;
84*e4b17023SJohn Marino   /* Size of element in the pool.  */
85*e4b17023SJohn Marino   int elt_size;
86*e4b17023SJohn Marino };
87*e4b17023SJohn Marino 
88*e4b17023SJohn Marino /* Hashtable mapping alloc_pool names to descriptors.  */
89*e4b17023SJohn Marino static htab_t alloc_pool_hash;
90*e4b17023SJohn Marino 
91*e4b17023SJohn Marino /* Hashtable helpers.  */
92*e4b17023SJohn Marino static hashval_t
hash_descriptor(const void * p)93*e4b17023SJohn Marino hash_descriptor (const void *p)
94*e4b17023SJohn Marino {
95*e4b17023SJohn Marino   const struct alloc_pool_descriptor *const d =
96*e4b17023SJohn Marino     (const struct alloc_pool_descriptor * )p;
97*e4b17023SJohn Marino   return htab_hash_pointer (d->name);
98*e4b17023SJohn Marino }
99*e4b17023SJohn Marino static int
eq_descriptor(const void * p1,const void * p2)100*e4b17023SJohn Marino eq_descriptor (const void *p1, const void *p2)
101*e4b17023SJohn Marino {
102*e4b17023SJohn Marino   const struct alloc_pool_descriptor *const d =
103*e4b17023SJohn Marino     (const struct alloc_pool_descriptor *) p1;
104*e4b17023SJohn Marino   return d->name == p2;
105*e4b17023SJohn Marino }
106*e4b17023SJohn Marino 
107*e4b17023SJohn Marino /* For given name, return descriptor, create new if needed.  */
108*e4b17023SJohn Marino static struct alloc_pool_descriptor *
alloc_pool_descriptor(const char * name)109*e4b17023SJohn Marino alloc_pool_descriptor (const char *name)
110*e4b17023SJohn Marino {
111*e4b17023SJohn Marino   struct alloc_pool_descriptor **slot;
112*e4b17023SJohn Marino 
113*e4b17023SJohn Marino   if (!alloc_pool_hash)
114*e4b17023SJohn Marino     alloc_pool_hash = htab_create (10, hash_descriptor, eq_descriptor, NULL);
115*e4b17023SJohn Marino 
116*e4b17023SJohn Marino   slot = (struct alloc_pool_descriptor **)
117*e4b17023SJohn Marino     htab_find_slot_with_hash (alloc_pool_hash, name,
118*e4b17023SJohn Marino 			      htab_hash_pointer (name),
119*e4b17023SJohn Marino 			      INSERT);
120*e4b17023SJohn Marino   if (*slot)
121*e4b17023SJohn Marino     return *slot;
122*e4b17023SJohn Marino   *slot = XCNEW (struct alloc_pool_descriptor);
123*e4b17023SJohn Marino   (*slot)->name = name;
124*e4b17023SJohn Marino   return *slot;
125*e4b17023SJohn Marino }
126*e4b17023SJohn Marino #endif
127*e4b17023SJohn Marino 
128*e4b17023SJohn Marino /* Create a pool of things of size SIZE, with NUM in each block we
129*e4b17023SJohn Marino    allocate.  */
130*e4b17023SJohn Marino 
131*e4b17023SJohn Marino alloc_pool
create_alloc_pool(const char * name,size_t size,size_t num)132*e4b17023SJohn Marino create_alloc_pool (const char *name, size_t size, size_t num)
133*e4b17023SJohn Marino {
134*e4b17023SJohn Marino   alloc_pool pool;
135*e4b17023SJohn Marino   size_t header_size;
136*e4b17023SJohn Marino #ifdef GATHER_STATISTICS
137*e4b17023SJohn Marino   struct alloc_pool_descriptor *desc;
138*e4b17023SJohn Marino #endif
139*e4b17023SJohn Marino 
140*e4b17023SJohn Marino   gcc_checking_assert (name);
141*e4b17023SJohn Marino 
142*e4b17023SJohn Marino   /* Make size large enough to store the list header.  */
143*e4b17023SJohn Marino   if (size < sizeof (alloc_pool_list))
144*e4b17023SJohn Marino     size = sizeof (alloc_pool_list);
145*e4b17023SJohn Marino 
146*e4b17023SJohn Marino   /* Now align the size to a multiple of 4.  */
147*e4b17023SJohn Marino   size = align_eight (size);
148*e4b17023SJohn Marino 
149*e4b17023SJohn Marino #ifdef ENABLE_CHECKING
150*e4b17023SJohn Marino   /* Add the aligned size of ID.  */
151*e4b17023SJohn Marino   size += offsetof (allocation_object, u.data);
152*e4b17023SJohn Marino #endif
153*e4b17023SJohn Marino 
154*e4b17023SJohn Marino   /* Um, we can't really allocate 0 elements per block.  */
155*e4b17023SJohn Marino   gcc_checking_assert (num);
156*e4b17023SJohn Marino 
157*e4b17023SJohn Marino   /* Allocate memory for the pool structure.  */
158*e4b17023SJohn Marino   pool = XNEW (struct alloc_pool_def);
159*e4b17023SJohn Marino 
160*e4b17023SJohn Marino   /* Now init the various pieces of our pool structure.  */
161*e4b17023SJohn Marino   pool->name = /*xstrdup (name)*/name;
162*e4b17023SJohn Marino #ifdef GATHER_STATISTICS
163*e4b17023SJohn Marino   desc = alloc_pool_descriptor (name);
164*e4b17023SJohn Marino   desc->elt_size = size;
165*e4b17023SJohn Marino   desc->created++;
166*e4b17023SJohn Marino #endif
167*e4b17023SJohn Marino   pool->elt_size = size;
168*e4b17023SJohn Marino   pool->elts_per_block = num;
169*e4b17023SJohn Marino 
170*e4b17023SJohn Marino   /* List header size should be a multiple of 8.  */
171*e4b17023SJohn Marino   header_size = align_eight (sizeof (struct alloc_pool_list_def));
172*e4b17023SJohn Marino 
173*e4b17023SJohn Marino   pool->block_size = (size * num) + header_size;
174*e4b17023SJohn Marino   pool->returned_free_list = NULL;
175*e4b17023SJohn Marino   pool->virgin_free_list = NULL;
176*e4b17023SJohn Marino   pool->virgin_elts_remaining = 0;
177*e4b17023SJohn Marino   pool->elts_allocated = 0;
178*e4b17023SJohn Marino   pool->elts_free = 0;
179*e4b17023SJohn Marino   pool->blocks_allocated = 0;
180*e4b17023SJohn Marino   pool->block_list = NULL;
181*e4b17023SJohn Marino 
182*e4b17023SJohn Marino #ifdef ENABLE_CHECKING
183*e4b17023SJohn Marino   /* Increase the last used ID and use it for this pool.
184*e4b17023SJohn Marino      ID == 0 is used for free elements of pool so skip it.  */
185*e4b17023SJohn Marino   last_id++;
186*e4b17023SJohn Marino   if (last_id == 0)
187*e4b17023SJohn Marino     last_id++;
188*e4b17023SJohn Marino 
189*e4b17023SJohn Marino   pool->id = last_id;
190*e4b17023SJohn Marino #endif
191*e4b17023SJohn Marino 
192*e4b17023SJohn Marino   return (pool);
193*e4b17023SJohn Marino }
194*e4b17023SJohn Marino 
195*e4b17023SJohn Marino /* Free all memory allocated for the given memory pool.  */
196*e4b17023SJohn Marino void
empty_alloc_pool(alloc_pool pool)197*e4b17023SJohn Marino empty_alloc_pool (alloc_pool pool)
198*e4b17023SJohn Marino {
199*e4b17023SJohn Marino   alloc_pool_list block, next_block;
200*e4b17023SJohn Marino #ifdef GATHER_STATISTICS
201*e4b17023SJohn Marino   struct alloc_pool_descriptor *desc = alloc_pool_descriptor (pool->name);
202*e4b17023SJohn Marino #endif
203*e4b17023SJohn Marino 
204*e4b17023SJohn Marino   gcc_checking_assert (pool);
205*e4b17023SJohn Marino 
206*e4b17023SJohn Marino   /* Free each block allocated to the pool.  */
207*e4b17023SJohn Marino   for (block = pool->block_list; block != NULL; block = next_block)
208*e4b17023SJohn Marino     {
209*e4b17023SJohn Marino       next_block = block->next;
210*e4b17023SJohn Marino       free (block);
211*e4b17023SJohn Marino     }
212*e4b17023SJohn Marino 
213*e4b17023SJohn Marino #ifdef GATHER_STATISTICS
214*e4b17023SJohn Marino   desc->current -= (pool->elts_allocated - pool->elts_free) * pool->elt_size;
215*e4b17023SJohn Marino #endif
216*e4b17023SJohn Marino   pool->returned_free_list = NULL;
217*e4b17023SJohn Marino   pool->virgin_free_list = NULL;
218*e4b17023SJohn Marino   pool->virgin_elts_remaining = 0;
219*e4b17023SJohn Marino   pool->elts_allocated = 0;
220*e4b17023SJohn Marino   pool->elts_free = 0;
221*e4b17023SJohn Marino   pool->blocks_allocated = 0;
222*e4b17023SJohn Marino   pool->block_list = NULL;
223*e4b17023SJohn Marino }
224*e4b17023SJohn Marino 
225*e4b17023SJohn Marino /* Free all memory allocated for the given memory pool and the pool itself.  */
226*e4b17023SJohn Marino void
free_alloc_pool(alloc_pool pool)227*e4b17023SJohn Marino free_alloc_pool (alloc_pool pool)
228*e4b17023SJohn Marino {
229*e4b17023SJohn Marino   /* First empty the pool.  */
230*e4b17023SJohn Marino   empty_alloc_pool (pool);
231*e4b17023SJohn Marino #ifdef ENABLE_CHECKING
232*e4b17023SJohn Marino   memset (pool, 0xaf, sizeof (*pool));
233*e4b17023SJohn Marino #endif
234*e4b17023SJohn Marino   /* Lastly, free the pool.  */
235*e4b17023SJohn Marino   free (pool);
236*e4b17023SJohn Marino }
237*e4b17023SJohn Marino 
238*e4b17023SJohn Marino /* Frees the alloc_pool, if it is empty and zero *POOL in this case.  */
239*e4b17023SJohn Marino void
free_alloc_pool_if_empty(alloc_pool * pool)240*e4b17023SJohn Marino free_alloc_pool_if_empty (alloc_pool *pool)
241*e4b17023SJohn Marino {
242*e4b17023SJohn Marino   if ((*pool)->elts_free == (*pool)->elts_allocated)
243*e4b17023SJohn Marino     {
244*e4b17023SJohn Marino       free_alloc_pool (*pool);
245*e4b17023SJohn Marino       *pool = NULL;
246*e4b17023SJohn Marino     }
247*e4b17023SJohn Marino }
248*e4b17023SJohn Marino 
249*e4b17023SJohn Marino /* Allocates one element from the pool specified.  */
250*e4b17023SJohn Marino void *
pool_alloc(alloc_pool pool)251*e4b17023SJohn Marino pool_alloc (alloc_pool pool)
252*e4b17023SJohn Marino {
253*e4b17023SJohn Marino   alloc_pool_list header;
254*e4b17023SJohn Marino #ifdef GATHER_STATISTICS
255*e4b17023SJohn Marino   struct alloc_pool_descriptor *desc = alloc_pool_descriptor (pool->name);
256*e4b17023SJohn Marino 
257*e4b17023SJohn Marino   desc->allocated += pool->elt_size;
258*e4b17023SJohn Marino   desc->current += pool->elt_size;
259*e4b17023SJohn Marino   if (desc->peak < desc->current)
260*e4b17023SJohn Marino     desc->peak = desc->current;
261*e4b17023SJohn Marino #endif
262*e4b17023SJohn Marino 
263*e4b17023SJohn Marino   gcc_checking_assert (pool);
264*e4b17023SJohn Marino 
265*e4b17023SJohn Marino   /* If there are no more free elements, make some more!.  */
266*e4b17023SJohn Marino   if (!pool->returned_free_list)
267*e4b17023SJohn Marino     {
268*e4b17023SJohn Marino       char *block;
269*e4b17023SJohn Marino       if (!pool->virgin_elts_remaining)
270*e4b17023SJohn Marino 	{
271*e4b17023SJohn Marino 	  alloc_pool_list block_header;
272*e4b17023SJohn Marino 
273*e4b17023SJohn Marino 	  /* Make the block.  */
274*e4b17023SJohn Marino 	  block = XNEWVEC (char, pool->block_size);
275*e4b17023SJohn Marino 	  block_header = (alloc_pool_list) block;
276*e4b17023SJohn Marino 	  block += align_eight (sizeof (struct alloc_pool_list_def));
277*e4b17023SJohn Marino 
278*e4b17023SJohn Marino 	  /* Throw it on the block list.  */
279*e4b17023SJohn Marino 	  block_header->next = pool->block_list;
280*e4b17023SJohn Marino 	  pool->block_list = block_header;
281*e4b17023SJohn Marino 
282*e4b17023SJohn Marino 	  /* Make the block available for allocation.  */
283*e4b17023SJohn Marino 	  pool->virgin_free_list = block;
284*e4b17023SJohn Marino 	  pool->virgin_elts_remaining = pool->elts_per_block;
285*e4b17023SJohn Marino 
286*e4b17023SJohn Marino 	  /* Also update the number of elements we have free/allocated, and
287*e4b17023SJohn Marino 	     increment the allocated block count.  */
288*e4b17023SJohn Marino 	  pool->elts_allocated += pool->elts_per_block;
289*e4b17023SJohn Marino 	  pool->elts_free += pool->elts_per_block;
290*e4b17023SJohn Marino 	  pool->blocks_allocated += 1;
291*e4b17023SJohn Marino 	}
292*e4b17023SJohn Marino 
293*e4b17023SJohn Marino 
294*e4b17023SJohn Marino       /* We now know that we can take the first elt off the virgin list and
295*e4b17023SJohn Marino 	 put it on the returned list. */
296*e4b17023SJohn Marino       block = pool->virgin_free_list;
297*e4b17023SJohn Marino       header = (alloc_pool_list) USER_PTR_FROM_ALLOCATION_OBJECT_PTR (block);
298*e4b17023SJohn Marino       header->next = NULL;
299*e4b17023SJohn Marino #ifdef ENABLE_CHECKING
300*e4b17023SJohn Marino       /* Mark the element to be free.  */
301*e4b17023SJohn Marino       ((allocation_object *) block)->id = 0;
302*e4b17023SJohn Marino #endif
303*e4b17023SJohn Marino       pool->returned_free_list = header;
304*e4b17023SJohn Marino       pool->virgin_free_list += pool->elt_size;
305*e4b17023SJohn Marino       pool->virgin_elts_remaining--;
306*e4b17023SJohn Marino 
307*e4b17023SJohn Marino     }
308*e4b17023SJohn Marino 
309*e4b17023SJohn Marino   /* Pull the first free element from the free list, and return it.  */
310*e4b17023SJohn Marino   header = pool->returned_free_list;
311*e4b17023SJohn Marino   pool->returned_free_list = header->next;
312*e4b17023SJohn Marino   pool->elts_free--;
313*e4b17023SJohn Marino 
314*e4b17023SJohn Marino #ifdef ENABLE_CHECKING
315*e4b17023SJohn Marino   /* Set the ID for element.  */
316*e4b17023SJohn Marino   ALLOCATION_OBJECT_PTR_FROM_USER_PTR (header)->id = pool->id;
317*e4b17023SJohn Marino #endif
318*e4b17023SJohn Marino 
319*e4b17023SJohn Marino   return ((void *) header);
320*e4b17023SJohn Marino }
321*e4b17023SJohn Marino 
322*e4b17023SJohn Marino /* Puts PTR back on POOL's free list.  */
323*e4b17023SJohn Marino void
pool_free(alloc_pool pool,void * ptr)324*e4b17023SJohn Marino pool_free (alloc_pool pool, void *ptr)
325*e4b17023SJohn Marino {
326*e4b17023SJohn Marino   alloc_pool_list header;
327*e4b17023SJohn Marino #ifdef GATHER_STATISTICS
328*e4b17023SJohn Marino   struct alloc_pool_descriptor *desc = alloc_pool_descriptor (pool->name);
329*e4b17023SJohn Marino #endif
330*e4b17023SJohn Marino 
331*e4b17023SJohn Marino 
332*e4b17023SJohn Marino #ifdef ENABLE_CHECKING
333*e4b17023SJohn Marino   gcc_assert (ptr
334*e4b17023SJohn Marino 	      /* Check if we free more than we allocated, which is Bad (TM).  */
335*e4b17023SJohn Marino 	      && pool->elts_free < pool->elts_allocated
336*e4b17023SJohn Marino 	      /* Check whether the PTR was allocated from POOL.  */
337*e4b17023SJohn Marino 	      && pool->id == ALLOCATION_OBJECT_PTR_FROM_USER_PTR (ptr)->id);
338*e4b17023SJohn Marino 
339*e4b17023SJohn Marino   memset (ptr, 0xaf, pool->elt_size - offsetof (allocation_object, u.data));
340*e4b17023SJohn Marino 
341*e4b17023SJohn Marino   /* Mark the element to be free.  */
342*e4b17023SJohn Marino   ALLOCATION_OBJECT_PTR_FROM_USER_PTR (ptr)->id = 0;
343*e4b17023SJohn Marino #else
344*e4b17023SJohn Marino #endif
345*e4b17023SJohn Marino 
346*e4b17023SJohn Marino   header = (alloc_pool_list) ptr;
347*e4b17023SJohn Marino   header->next = pool->returned_free_list;
348*e4b17023SJohn Marino   pool->returned_free_list = header;
349*e4b17023SJohn Marino   pool->elts_free++;
350*e4b17023SJohn Marino 
351*e4b17023SJohn Marino #ifdef GATHER_STATISTICS
352*e4b17023SJohn Marino   desc->current -= pool->elt_size;
353*e4b17023SJohn Marino #endif
354*e4b17023SJohn Marino 
355*e4b17023SJohn Marino }
356*e4b17023SJohn Marino /* Output per-alloc_pool statistics.  */
357*e4b17023SJohn Marino #ifdef GATHER_STATISTICS
358*e4b17023SJohn Marino 
359*e4b17023SJohn Marino /* Used to accumulate statistics about alloc_pool sizes.  */
360*e4b17023SJohn Marino struct output_info
361*e4b17023SJohn Marino {
362*e4b17023SJohn Marino   unsigned long total_created;
363*e4b17023SJohn Marino   unsigned long total_allocated;
364*e4b17023SJohn Marino };
365*e4b17023SJohn Marino 
366*e4b17023SJohn Marino /* Called via htab_traverse.  Output alloc_pool descriptor pointed out by SLOT
367*e4b17023SJohn Marino    and update statistics.  */
368*e4b17023SJohn Marino static int
print_statistics(void ** slot,void * b)369*e4b17023SJohn Marino print_statistics (void **slot, void *b)
370*e4b17023SJohn Marino {
371*e4b17023SJohn Marino   struct alloc_pool_descriptor *d = (struct alloc_pool_descriptor *) *slot;
372*e4b17023SJohn Marino   struct output_info *i = (struct output_info *) b;
373*e4b17023SJohn Marino 
374*e4b17023SJohn Marino   if (d->allocated)
375*e4b17023SJohn Marino     {
376*e4b17023SJohn Marino       fprintf (stderr, "%-22s %6d %10lu %10lu(%10lu) %10lu(%10lu) %10lu(%10lu)\n", d->name,
377*e4b17023SJohn Marino 	       d->elt_size, d->created, d->allocated, d->allocated / d->elt_size,
378*e4b17023SJohn Marino 	       d->peak, d->peak / d->elt_size,
379*e4b17023SJohn Marino 	       d->current, d->current / d->elt_size);
380*e4b17023SJohn Marino       i->total_allocated += d->allocated;
381*e4b17023SJohn Marino       i->total_created += d->created;
382*e4b17023SJohn Marino     }
383*e4b17023SJohn Marino   return 1;
384*e4b17023SJohn Marino }
385*e4b17023SJohn Marino #endif
386*e4b17023SJohn Marino 
387*e4b17023SJohn Marino /* Output per-alloc_pool memory usage statistics.  */
388*e4b17023SJohn Marino void
dump_alloc_pool_statistics(void)389*e4b17023SJohn Marino dump_alloc_pool_statistics (void)
390*e4b17023SJohn Marino {
391*e4b17023SJohn Marino #ifdef GATHER_STATISTICS
392*e4b17023SJohn Marino   struct output_info info;
393*e4b17023SJohn Marino 
394*e4b17023SJohn Marino   if (!alloc_pool_hash)
395*e4b17023SJohn Marino     return;
396*e4b17023SJohn Marino 
397*e4b17023SJohn Marino   fprintf (stderr, "\nAlloc-pool Kind         Elt size  Pools  Allocated (elts)            Peak (elts)            Leak (elts)\n");
398*e4b17023SJohn Marino   fprintf (stderr, "--------------------------------------------------------------------------------------------------------------\n");
399*e4b17023SJohn Marino   info.total_created = 0;
400*e4b17023SJohn Marino   info.total_allocated = 0;
401*e4b17023SJohn Marino   htab_traverse (alloc_pool_hash, print_statistics, &info);
402*e4b17023SJohn Marino   fprintf (stderr, "--------------------------------------------------------------------------------------------------------------\n");
403*e4b17023SJohn Marino   fprintf (stderr, "%-22s           %7lu %10lu\n",
404*e4b17023SJohn Marino 	   "Total", info.total_created, info.total_allocated);
405*e4b17023SJohn Marino   fprintf (stderr, "--------------------------------------------------------------------------------------------------------------\n");
406*e4b17023SJohn Marino #endif
407*e4b17023SJohn Marino }
408