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