xref: /dflybsd-src/contrib/gcc-4.7/gcc/vec.c (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
1*e4b17023SJohn Marino /* Vector API for GNU compiler.
2*e4b17023SJohn Marino    Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010
3*e4b17023SJohn Marino    Free Software Foundation, Inc.
4*e4b17023SJohn Marino    Contributed by Nathan Sidwell <nathan@codesourcery.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 /* This file is compiled twice: once for the generator programs
23*e4b17023SJohn Marino    once for the compiler.  */
24*e4b17023SJohn Marino #ifdef GENERATOR_FILE
25*e4b17023SJohn Marino #include "bconfig.h"
26*e4b17023SJohn Marino #else
27*e4b17023SJohn Marino #include "config.h"
28*e4b17023SJohn Marino #endif
29*e4b17023SJohn Marino 
30*e4b17023SJohn Marino #include "system.h"
31*e4b17023SJohn Marino #include "coretypes.h"
32*e4b17023SJohn Marino #include "ggc.h"
33*e4b17023SJohn Marino #include "vec.h"
34*e4b17023SJohn Marino #include "diagnostic-core.h"
35*e4b17023SJohn Marino #include "hashtab.h"
36*e4b17023SJohn Marino 
37*e4b17023SJohn Marino #ifdef GATHER_STATISTICS
38*e4b17023SJohn Marino 
39*e4b17023SJohn Marino /* Store information about each particular vector.  */
40*e4b17023SJohn Marino struct vec_descriptor
41*e4b17023SJohn Marino {
42*e4b17023SJohn Marino   const char *function;
43*e4b17023SJohn Marino   const char *file;
44*e4b17023SJohn Marino   int line;
45*e4b17023SJohn Marino   size_t allocated;
46*e4b17023SJohn Marino   size_t times;
47*e4b17023SJohn Marino   size_t peak;
48*e4b17023SJohn Marino };
49*e4b17023SJohn Marino 
50*e4b17023SJohn Marino 
51*e4b17023SJohn Marino /* Hashtable mapping vec addresses to descriptors.  */
52*e4b17023SJohn Marino static htab_t vec_desc_hash;
53*e4b17023SJohn Marino 
54*e4b17023SJohn Marino /* Hashtable helpers.  */
55*e4b17023SJohn Marino static hashval_t
hash_descriptor(const void * p)56*e4b17023SJohn Marino hash_descriptor (const void *p)
57*e4b17023SJohn Marino {
58*e4b17023SJohn Marino   const struct vec_descriptor *const d =
59*e4b17023SJohn Marino     (const struct vec_descriptor *) p;
60*e4b17023SJohn Marino   return htab_hash_pointer (d->file) + d->line;
61*e4b17023SJohn Marino }
62*e4b17023SJohn Marino static int
eq_descriptor(const void * p1,const void * p2)63*e4b17023SJohn Marino eq_descriptor (const void *p1, const void *p2)
64*e4b17023SJohn Marino {
65*e4b17023SJohn Marino   const struct vec_descriptor *const d = (const struct vec_descriptor *) p1;
66*e4b17023SJohn Marino   const struct vec_descriptor *const l = (const struct vec_descriptor *) p2;
67*e4b17023SJohn Marino   return d->file == l->file && d->function == l->function && d->line == l->line;
68*e4b17023SJohn Marino }
69*e4b17023SJohn Marino 
70*e4b17023SJohn Marino /* Hashtable converting address of allocated field to loc descriptor.  */
71*e4b17023SJohn Marino static htab_t ptr_hash;
72*e4b17023SJohn Marino struct ptr_hash_entry
73*e4b17023SJohn Marino {
74*e4b17023SJohn Marino   void *ptr;
75*e4b17023SJohn Marino   struct vec_descriptor *loc;
76*e4b17023SJohn Marino   size_t allocated;
77*e4b17023SJohn Marino };
78*e4b17023SJohn Marino 
79*e4b17023SJohn Marino /* Hash table helpers functions.  */
80*e4b17023SJohn Marino static hashval_t
hash_ptr(const void * p)81*e4b17023SJohn Marino hash_ptr (const void *p)
82*e4b17023SJohn Marino {
83*e4b17023SJohn Marino   const struct ptr_hash_entry *const d = (const struct ptr_hash_entry *) p;
84*e4b17023SJohn Marino 
85*e4b17023SJohn Marino   return htab_hash_pointer (d->ptr);
86*e4b17023SJohn Marino }
87*e4b17023SJohn Marino 
88*e4b17023SJohn Marino static int
eq_ptr(const void * p1,const void * p2)89*e4b17023SJohn Marino eq_ptr (const void *p1, const void *p2)
90*e4b17023SJohn Marino {
91*e4b17023SJohn Marino   const struct ptr_hash_entry *const p = (const struct ptr_hash_entry *) p1;
92*e4b17023SJohn Marino 
93*e4b17023SJohn Marino   return (p->ptr == p2);
94*e4b17023SJohn Marino }
95*e4b17023SJohn Marino 
96*e4b17023SJohn Marino /* Return descriptor for given call site, create new one if needed.  */
97*e4b17023SJohn Marino static struct vec_descriptor *
vec_descriptor(const char * name,int line,const char * function)98*e4b17023SJohn Marino vec_descriptor (const char *name, int line, const char *function)
99*e4b17023SJohn Marino {
100*e4b17023SJohn Marino   struct vec_descriptor loc;
101*e4b17023SJohn Marino   struct vec_descriptor **slot;
102*e4b17023SJohn Marino 
103*e4b17023SJohn Marino   loc.file = name;
104*e4b17023SJohn Marino   loc.line = line;
105*e4b17023SJohn Marino   loc.function = function;
106*e4b17023SJohn Marino   if (!vec_desc_hash)
107*e4b17023SJohn Marino     vec_desc_hash = htab_create (10, hash_descriptor, eq_descriptor, NULL);
108*e4b17023SJohn Marino 
109*e4b17023SJohn Marino   slot = (struct vec_descriptor **) htab_find_slot (vec_desc_hash, &loc,
110*e4b17023SJohn Marino 						    INSERT);
111*e4b17023SJohn Marino   if (*slot)
112*e4b17023SJohn Marino     return *slot;
113*e4b17023SJohn Marino   *slot = XCNEW (struct vec_descriptor);
114*e4b17023SJohn Marino   (*slot)->file = name;
115*e4b17023SJohn Marino   (*slot)->line = line;
116*e4b17023SJohn Marino   (*slot)->function = function;
117*e4b17023SJohn Marino   (*slot)->allocated = 0;
118*e4b17023SJohn Marino   (*slot)->peak = 0;
119*e4b17023SJohn Marino   return *slot;
120*e4b17023SJohn Marino }
121*e4b17023SJohn Marino 
122*e4b17023SJohn Marino /* Account the overhead.  */
123*e4b17023SJohn Marino static void
register_overhead(struct vec_prefix * ptr,size_t size,const char * name,int line,const char * function)124*e4b17023SJohn Marino register_overhead (struct vec_prefix *ptr, size_t size,
125*e4b17023SJohn Marino 		   const char *name, int line, const char *function)
126*e4b17023SJohn Marino {
127*e4b17023SJohn Marino   struct vec_descriptor *loc = vec_descriptor (name, line, function);
128*e4b17023SJohn Marino   struct ptr_hash_entry *p = XNEW (struct ptr_hash_entry);
129*e4b17023SJohn Marino   PTR *slot;
130*e4b17023SJohn Marino 
131*e4b17023SJohn Marino   p->ptr = ptr;
132*e4b17023SJohn Marino   p->loc = loc;
133*e4b17023SJohn Marino   p->allocated = size;
134*e4b17023SJohn Marino   if (!ptr_hash)
135*e4b17023SJohn Marino     ptr_hash = htab_create (10, hash_ptr, eq_ptr, NULL);
136*e4b17023SJohn Marino   slot = htab_find_slot_with_hash (ptr_hash, ptr, htab_hash_pointer (ptr), INSERT);
137*e4b17023SJohn Marino   gcc_assert (!*slot);
138*e4b17023SJohn Marino   *slot = p;
139*e4b17023SJohn Marino 
140*e4b17023SJohn Marino   loc->allocated += size;
141*e4b17023SJohn Marino   if (loc->peak < loc->allocated)
142*e4b17023SJohn Marino     loc->peak += loc->allocated;
143*e4b17023SJohn Marino   loc->times++;
144*e4b17023SJohn Marino }
145*e4b17023SJohn Marino 
146*e4b17023SJohn Marino /* Notice that the pointer has been freed.  */
147*e4b17023SJohn Marino static void
free_overhead(struct vec_prefix * ptr)148*e4b17023SJohn Marino free_overhead (struct vec_prefix *ptr)
149*e4b17023SJohn Marino {
150*e4b17023SJohn Marino   PTR *slot = htab_find_slot_with_hash (ptr_hash, ptr, htab_hash_pointer (ptr),
151*e4b17023SJohn Marino 					NO_INSERT);
152*e4b17023SJohn Marino   struct ptr_hash_entry *p = (struct ptr_hash_entry *) *slot;
153*e4b17023SJohn Marino   p->loc->allocated -= p->allocated;
154*e4b17023SJohn Marino   htab_clear_slot (ptr_hash, slot);
155*e4b17023SJohn Marino   free (p);
156*e4b17023SJohn Marino }
157*e4b17023SJohn Marino 
158*e4b17023SJohn Marino void
vec_heap_free(void * ptr)159*e4b17023SJohn Marino vec_heap_free (void *ptr)
160*e4b17023SJohn Marino {
161*e4b17023SJohn Marino   free_overhead ((struct vec_prefix *)ptr);
162*e4b17023SJohn Marino   free (ptr);
163*e4b17023SJohn Marino }
164*e4b17023SJohn Marino #endif
165*e4b17023SJohn Marino 
166*e4b17023SJohn Marino /* Calculate the new ALLOC value, making sure that RESERVE slots are
167*e4b17023SJohn Marino    free.  If EXACT grow exactly, otherwise grow exponentially.  */
168*e4b17023SJohn Marino 
169*e4b17023SJohn Marino static inline unsigned
calculate_allocation(const struct vec_prefix * pfx,int reserve,bool exact)170*e4b17023SJohn Marino calculate_allocation (const struct vec_prefix *pfx, int reserve, bool exact)
171*e4b17023SJohn Marino {
172*e4b17023SJohn Marino   unsigned alloc = 0;
173*e4b17023SJohn Marino   unsigned num = 0;
174*e4b17023SJohn Marino 
175*e4b17023SJohn Marino   gcc_assert (reserve >= 0);
176*e4b17023SJohn Marino 
177*e4b17023SJohn Marino   if (pfx)
178*e4b17023SJohn Marino     {
179*e4b17023SJohn Marino       alloc = pfx->alloc;
180*e4b17023SJohn Marino       num = pfx->num;
181*e4b17023SJohn Marino     }
182*e4b17023SJohn Marino   else if (!reserve)
183*e4b17023SJohn Marino     /* If there's no prefix, and we've not requested anything, then we
184*e4b17023SJohn Marino        will create a NULL vector.  */
185*e4b17023SJohn Marino     return 0;
186*e4b17023SJohn Marino 
187*e4b17023SJohn Marino   /* We must have run out of room.  */
188*e4b17023SJohn Marino   gcc_assert (alloc - num < (unsigned) reserve);
189*e4b17023SJohn Marino 
190*e4b17023SJohn Marino   if (exact)
191*e4b17023SJohn Marino     /* Exact size.  */
192*e4b17023SJohn Marino     alloc = num + reserve;
193*e4b17023SJohn Marino   else
194*e4b17023SJohn Marino     {
195*e4b17023SJohn Marino       /* Exponential growth. */
196*e4b17023SJohn Marino       if (!alloc)
197*e4b17023SJohn Marino 	alloc = 4;
198*e4b17023SJohn Marino       else if (alloc < 16)
199*e4b17023SJohn Marino 	/* Double when small.  */
200*e4b17023SJohn Marino 	alloc = alloc * 2;
201*e4b17023SJohn Marino       else
202*e4b17023SJohn Marino 	/* Grow slower when large.  */
203*e4b17023SJohn Marino 	alloc = (alloc * 3 / 2);
204*e4b17023SJohn Marino 
205*e4b17023SJohn Marino       /* If this is still too small, set it to the right size. */
206*e4b17023SJohn Marino       if (alloc < num + reserve)
207*e4b17023SJohn Marino 	alloc = num + reserve;
208*e4b17023SJohn Marino     }
209*e4b17023SJohn Marino   return alloc;
210*e4b17023SJohn Marino }
211*e4b17023SJohn Marino 
212*e4b17023SJohn Marino /* Ensure there are at least RESERVE free slots in VEC.  If EXACT grow
213*e4b17023SJohn Marino    exactly, else grow exponentially.  As a special case, if VEC is
214*e4b17023SJohn Marino    NULL and RESERVE is 0, no vector will be created.  The vector's
215*e4b17023SJohn Marino    trailing array is at VEC_OFFSET offset and consists of ELT_SIZE
216*e4b17023SJohn Marino    sized elements.  */
217*e4b17023SJohn Marino 
218*e4b17023SJohn Marino static void *
vec_gc_o_reserve_1(void * vec,int reserve,size_t vec_offset,size_t elt_size,bool exact MEM_STAT_DECL)219*e4b17023SJohn Marino vec_gc_o_reserve_1 (void *vec, int reserve, size_t vec_offset, size_t elt_size,
220*e4b17023SJohn Marino 		    bool exact MEM_STAT_DECL)
221*e4b17023SJohn Marino {
222*e4b17023SJohn Marino   struct vec_prefix *pfx = (struct vec_prefix *) vec;
223*e4b17023SJohn Marino   unsigned alloc = calculate_allocation (pfx, reserve, exact);
224*e4b17023SJohn Marino   size_t size;
225*e4b17023SJohn Marino 
226*e4b17023SJohn Marino   if (!alloc)
227*e4b17023SJohn Marino     {
228*e4b17023SJohn Marino       if (pfx)
229*e4b17023SJohn Marino         ggc_free (pfx);
230*e4b17023SJohn Marino       return NULL;
231*e4b17023SJohn Marino     }
232*e4b17023SJohn Marino 
233*e4b17023SJohn Marino   /* Calculate the amount of space we want.  */
234*e4b17023SJohn Marino   size = vec_offset + alloc * elt_size;
235*e4b17023SJohn Marino   /* Ask the allocator how much space it will really give us.  */
236*e4b17023SJohn Marino   size = ggc_round_alloc_size (size);
237*e4b17023SJohn Marino   /* Adjust the number of slots accordingly.  */
238*e4b17023SJohn Marino   alloc = (size - vec_offset) / elt_size;
239*e4b17023SJohn Marino   /* And finally, recalculate the amount of space we ask for.  */
240*e4b17023SJohn Marino   size = vec_offset + alloc * elt_size;
241*e4b17023SJohn Marino 
242*e4b17023SJohn Marino   vec = ggc_realloc_stat (vec, size PASS_MEM_STAT);
243*e4b17023SJohn Marino 
244*e4b17023SJohn Marino   ((struct vec_prefix *)vec)->alloc = alloc;
245*e4b17023SJohn Marino   if (!pfx)
246*e4b17023SJohn Marino     ((struct vec_prefix *)vec)->num = 0;
247*e4b17023SJohn Marino 
248*e4b17023SJohn Marino   return vec;
249*e4b17023SJohn Marino }
250*e4b17023SJohn Marino 
251*e4b17023SJohn Marino /* Ensure there are at least RESERVE free slots in VEC, growing
252*e4b17023SJohn Marino    exponentially.  If RESERVE < 0 grow exactly, else grow
253*e4b17023SJohn Marino    exponentially.  As a special case, if VEC is NULL, and RESERVE is
254*e4b17023SJohn Marino    0, no vector will be created. */
255*e4b17023SJohn Marino 
256*e4b17023SJohn Marino void *
vec_gc_p_reserve(void * vec,int reserve MEM_STAT_DECL)257*e4b17023SJohn Marino vec_gc_p_reserve (void *vec, int reserve MEM_STAT_DECL)
258*e4b17023SJohn Marino {
259*e4b17023SJohn Marino   return vec_gc_o_reserve_1 (vec, reserve,
260*e4b17023SJohn Marino 			     sizeof (struct vec_prefix),
261*e4b17023SJohn Marino 			     sizeof (void *), false
262*e4b17023SJohn Marino 			     PASS_MEM_STAT);
263*e4b17023SJohn Marino }
264*e4b17023SJohn Marino 
265*e4b17023SJohn Marino /* Ensure there are at least RESERVE free slots in VEC, growing
266*e4b17023SJohn Marino    exactly.  If RESERVE < 0 grow exactly, else grow exponentially.  As
267*e4b17023SJohn Marino    a special case, if VEC is NULL, and RESERVE is 0, no vector will be
268*e4b17023SJohn Marino    created. */
269*e4b17023SJohn Marino 
270*e4b17023SJohn Marino void *
vec_gc_p_reserve_exact(void * vec,int reserve MEM_STAT_DECL)271*e4b17023SJohn Marino vec_gc_p_reserve_exact (void *vec, int reserve MEM_STAT_DECL)
272*e4b17023SJohn Marino {
273*e4b17023SJohn Marino   return vec_gc_o_reserve_1 (vec, reserve,
274*e4b17023SJohn Marino 			     sizeof (struct vec_prefix),
275*e4b17023SJohn Marino 			     sizeof (void *), true
276*e4b17023SJohn Marino 			     PASS_MEM_STAT);
277*e4b17023SJohn Marino }
278*e4b17023SJohn Marino 
279*e4b17023SJohn Marino /* As for vec_gc_p_reserve, but for object vectors.  The vector's
280*e4b17023SJohn Marino    trailing array is at VEC_OFFSET offset and consists of ELT_SIZE
281*e4b17023SJohn Marino    sized elements.  */
282*e4b17023SJohn Marino 
283*e4b17023SJohn Marino void *
vec_gc_o_reserve(void * vec,int reserve,size_t vec_offset,size_t elt_size MEM_STAT_DECL)284*e4b17023SJohn Marino vec_gc_o_reserve (void *vec, int reserve, size_t vec_offset, size_t elt_size
285*e4b17023SJohn Marino 		  MEM_STAT_DECL)
286*e4b17023SJohn Marino {
287*e4b17023SJohn Marino   return vec_gc_o_reserve_1 (vec, reserve, vec_offset, elt_size, false
288*e4b17023SJohn Marino 			     PASS_MEM_STAT);
289*e4b17023SJohn Marino }
290*e4b17023SJohn Marino 
291*e4b17023SJohn Marino /* As for vec_gc_p_reserve_exact, but for object vectors.  The
292*e4b17023SJohn Marino    vector's trailing array is at VEC_OFFSET offset and consists of
293*e4b17023SJohn Marino    ELT_SIZE sized elements.  */
294*e4b17023SJohn Marino 
295*e4b17023SJohn Marino void *
vec_gc_o_reserve_exact(void * vec,int reserve,size_t vec_offset,size_t elt_size MEM_STAT_DECL)296*e4b17023SJohn Marino vec_gc_o_reserve_exact (void *vec, int reserve, size_t vec_offset,
297*e4b17023SJohn Marino 			size_t elt_size MEM_STAT_DECL)
298*e4b17023SJohn Marino {
299*e4b17023SJohn Marino   return vec_gc_o_reserve_1 (vec, reserve, vec_offset, elt_size, true
300*e4b17023SJohn Marino 			     PASS_MEM_STAT);
301*e4b17023SJohn Marino }
302*e4b17023SJohn Marino 
303*e4b17023SJohn Marino /* As for vec_gc_o_reserve_1, but for heap allocated vectors.  */
304*e4b17023SJohn Marino 
305*e4b17023SJohn Marino static void *
vec_heap_o_reserve_1(void * vec,int reserve,size_t vec_offset,size_t elt_size,bool exact MEM_STAT_DECL)306*e4b17023SJohn Marino vec_heap_o_reserve_1 (void *vec, int reserve, size_t vec_offset,
307*e4b17023SJohn Marino 		      size_t elt_size, bool exact MEM_STAT_DECL)
308*e4b17023SJohn Marino {
309*e4b17023SJohn Marino   struct vec_prefix *pfx = (struct vec_prefix *) vec;
310*e4b17023SJohn Marino   unsigned alloc = calculate_allocation (pfx, reserve, exact);
311*e4b17023SJohn Marino 
312*e4b17023SJohn Marino   if (!alloc)
313*e4b17023SJohn Marino     {
314*e4b17023SJohn Marino       if (pfx)
315*e4b17023SJohn Marino         vec_heap_free (pfx);
316*e4b17023SJohn Marino       return NULL;
317*e4b17023SJohn Marino     }
318*e4b17023SJohn Marino 
319*e4b17023SJohn Marino #ifdef GATHER_STATISTICS
320*e4b17023SJohn Marino   if (vec)
321*e4b17023SJohn Marino     free_overhead (pfx);
322*e4b17023SJohn Marino #endif
323*e4b17023SJohn Marino 
324*e4b17023SJohn Marino   vec = xrealloc (vec, vec_offset + alloc * elt_size);
325*e4b17023SJohn Marino   ((struct vec_prefix *)vec)->alloc = alloc;
326*e4b17023SJohn Marino   if (!pfx)
327*e4b17023SJohn Marino     ((struct vec_prefix *)vec)->num = 0;
328*e4b17023SJohn Marino #ifdef GATHER_STATISTICS
329*e4b17023SJohn Marino   if (vec)
330*e4b17023SJohn Marino     register_overhead ((struct vec_prefix *)vec,
331*e4b17023SJohn Marino     		       vec_offset + alloc * elt_size PASS_MEM_STAT);
332*e4b17023SJohn Marino #endif
333*e4b17023SJohn Marino 
334*e4b17023SJohn Marino   return vec;
335*e4b17023SJohn Marino }
336*e4b17023SJohn Marino 
337*e4b17023SJohn Marino /* As for vec_gc_p_reserve, but for heap allocated vectors.  */
338*e4b17023SJohn Marino 
339*e4b17023SJohn Marino void *
vec_heap_p_reserve(void * vec,int reserve MEM_STAT_DECL)340*e4b17023SJohn Marino vec_heap_p_reserve (void *vec, int reserve MEM_STAT_DECL)
341*e4b17023SJohn Marino {
342*e4b17023SJohn Marino   return vec_heap_o_reserve_1 (vec, reserve,
343*e4b17023SJohn Marino 			       sizeof (struct vec_prefix),
344*e4b17023SJohn Marino 			       sizeof (void *), false
345*e4b17023SJohn Marino 			       PASS_MEM_STAT);
346*e4b17023SJohn Marino }
347*e4b17023SJohn Marino 
348*e4b17023SJohn Marino /* As for vec_gc_p_reserve_exact, but for heap allocated vectors.  */
349*e4b17023SJohn Marino 
350*e4b17023SJohn Marino void *
vec_heap_p_reserve_exact(void * vec,int reserve MEM_STAT_DECL)351*e4b17023SJohn Marino vec_heap_p_reserve_exact (void *vec, int reserve MEM_STAT_DECL)
352*e4b17023SJohn Marino {
353*e4b17023SJohn Marino   return vec_heap_o_reserve_1 (vec, reserve,
354*e4b17023SJohn Marino 			       sizeof (struct vec_prefix),
355*e4b17023SJohn Marino 			       sizeof (void *), true
356*e4b17023SJohn Marino 			       PASS_MEM_STAT);
357*e4b17023SJohn Marino }
358*e4b17023SJohn Marino 
359*e4b17023SJohn Marino /* As for vec_gc_o_reserve, but for heap allocated vectors.  */
360*e4b17023SJohn Marino 
361*e4b17023SJohn Marino void *
vec_heap_o_reserve(void * vec,int reserve,size_t vec_offset,size_t elt_size MEM_STAT_DECL)362*e4b17023SJohn Marino vec_heap_o_reserve (void *vec, int reserve, size_t vec_offset, size_t elt_size
363*e4b17023SJohn Marino 		    MEM_STAT_DECL)
364*e4b17023SJohn Marino {
365*e4b17023SJohn Marino   return vec_heap_o_reserve_1 (vec, reserve, vec_offset, elt_size, false
366*e4b17023SJohn Marino 			       PASS_MEM_STAT);
367*e4b17023SJohn Marino }
368*e4b17023SJohn Marino 
369*e4b17023SJohn Marino /* As for vec_gc_o_reserve_exact, but for heap allocated vectors.  */
370*e4b17023SJohn Marino 
371*e4b17023SJohn Marino void *
vec_heap_o_reserve_exact(void * vec,int reserve,size_t vec_offset,size_t elt_size MEM_STAT_DECL)372*e4b17023SJohn Marino vec_heap_o_reserve_exact (void *vec, int reserve, size_t vec_offset,
373*e4b17023SJohn Marino 			  size_t elt_size MEM_STAT_DECL)
374*e4b17023SJohn Marino {
375*e4b17023SJohn Marino   return vec_heap_o_reserve_1 (vec, reserve, vec_offset, elt_size, true
376*e4b17023SJohn Marino 			       PASS_MEM_STAT);
377*e4b17023SJohn Marino }
378*e4b17023SJohn Marino 
379*e4b17023SJohn Marino /* Stack vectors are a little different.  VEC_alloc turns into a call
380*e4b17023SJohn Marino    to vec_stack_p_reserve_exact1 and passes in space allocated via a
381*e4b17023SJohn Marino    call to alloca.  We record that pointer so that we know that we
382*e4b17023SJohn Marino    shouldn't free it.  If the vector is resized, we resize it on the
383*e4b17023SJohn Marino    heap.  We record the pointers in a vector and search it in LIFO
384*e4b17023SJohn Marino    order--i.e., we look for the newest stack vectors first.  We don't
385*e4b17023SJohn Marino    expect too many stack vectors at any one level, and searching from
386*e4b17023SJohn Marino    the end should normally be efficient even if they are used in a
387*e4b17023SJohn Marino    recursive function.  */
388*e4b17023SJohn Marino 
389*e4b17023SJohn Marino typedef void *void_p;
390*e4b17023SJohn Marino DEF_VEC_P(void_p);
391*e4b17023SJohn Marino DEF_VEC_ALLOC_P(void_p,heap);
392*e4b17023SJohn Marino 
VEC(void_p,heap)393*e4b17023SJohn Marino static VEC(void_p,heap) *stack_vecs;
394*e4b17023SJohn Marino 
395*e4b17023SJohn Marino /* Allocate a vector which uses alloca for the initial allocation.
396*e4b17023SJohn Marino    SPACE is space allocated using alloca, ALLOC is the number of
397*e4b17023SJohn Marino    entries allocated.  */
398*e4b17023SJohn Marino 
399*e4b17023SJohn Marino void *
400*e4b17023SJohn Marino vec_stack_p_reserve_exact_1 (int alloc, void *space)
401*e4b17023SJohn Marino {
402*e4b17023SJohn Marino   struct vec_prefix *pfx = (struct vec_prefix *) space;
403*e4b17023SJohn Marino 
404*e4b17023SJohn Marino   VEC_safe_push (void_p, heap, stack_vecs, space);
405*e4b17023SJohn Marino 
406*e4b17023SJohn Marino   pfx->num = 0;
407*e4b17023SJohn Marino   pfx->alloc = alloc;
408*e4b17023SJohn Marino 
409*e4b17023SJohn Marino   return space;
410*e4b17023SJohn Marino }
411*e4b17023SJohn Marino 
412*e4b17023SJohn Marino /* Grow a vector allocated using alloca.  When this happens, we switch
413*e4b17023SJohn Marino    back to heap allocation.  We remove the vector from stack_vecs, if
414*e4b17023SJohn Marino    it is there, since we no longer need to avoid freeing it.  */
415*e4b17023SJohn Marino 
416*e4b17023SJohn Marino static void *
vec_stack_o_reserve_1(void * vec,int reserve,size_t vec_offset,size_t elt_size,bool exact MEM_STAT_DECL)417*e4b17023SJohn Marino vec_stack_o_reserve_1 (void *vec, int reserve, size_t vec_offset,
418*e4b17023SJohn Marino 		       size_t elt_size, bool exact MEM_STAT_DECL)
419*e4b17023SJohn Marino {
420*e4b17023SJohn Marino   bool found;
421*e4b17023SJohn Marino   unsigned int ix;
422*e4b17023SJohn Marino   void *newvec;
423*e4b17023SJohn Marino 
424*e4b17023SJohn Marino   found = false;
425*e4b17023SJohn Marino   for (ix = VEC_length (void_p, stack_vecs); ix > 0; --ix)
426*e4b17023SJohn Marino     {
427*e4b17023SJohn Marino       if (VEC_index (void_p, stack_vecs, ix - 1) == vec)
428*e4b17023SJohn Marino 	{
429*e4b17023SJohn Marino 	  VEC_unordered_remove (void_p, stack_vecs, ix - 1);
430*e4b17023SJohn Marino 	  found = true;
431*e4b17023SJohn Marino 	  break;
432*e4b17023SJohn Marino 	}
433*e4b17023SJohn Marino     }
434*e4b17023SJohn Marino 
435*e4b17023SJohn Marino   if (!found)
436*e4b17023SJohn Marino     {
437*e4b17023SJohn Marino       /* VEC is already on the heap.  */
438*e4b17023SJohn Marino       return vec_heap_o_reserve_1 (vec, reserve, vec_offset, elt_size,
439*e4b17023SJohn Marino 				   exact PASS_MEM_STAT);
440*e4b17023SJohn Marino     }
441*e4b17023SJohn Marino 
442*e4b17023SJohn Marino   /* Move VEC to the heap.  */
443*e4b17023SJohn Marino   reserve += ((struct vec_prefix *) vec)->num;
444*e4b17023SJohn Marino   newvec = vec_heap_o_reserve_1 (NULL, reserve, vec_offset, elt_size,
445*e4b17023SJohn Marino 				 exact PASS_MEM_STAT);
446*e4b17023SJohn Marino   if (newvec && vec)
447*e4b17023SJohn Marino     {
448*e4b17023SJohn Marino       ((struct vec_prefix *) newvec)->num = ((struct vec_prefix *) vec)->num;
449*e4b17023SJohn Marino       memcpy (((struct vec_prefix *) newvec)+1,
450*e4b17023SJohn Marino 	      ((struct vec_prefix *) vec)+1,
451*e4b17023SJohn Marino 	      ((struct vec_prefix *) vec)->num * elt_size);
452*e4b17023SJohn Marino     }
453*e4b17023SJohn Marino   return newvec;
454*e4b17023SJohn Marino }
455*e4b17023SJohn Marino 
456*e4b17023SJohn Marino /* Grow a vector allocated on the stack.  */
457*e4b17023SJohn Marino 
458*e4b17023SJohn Marino void *
vec_stack_p_reserve(void * vec,int reserve MEM_STAT_DECL)459*e4b17023SJohn Marino vec_stack_p_reserve (void *vec, int reserve MEM_STAT_DECL)
460*e4b17023SJohn Marino {
461*e4b17023SJohn Marino   return vec_stack_o_reserve_1 (vec, reserve,
462*e4b17023SJohn Marino 				sizeof (struct vec_prefix),
463*e4b17023SJohn Marino 				sizeof (void *), false
464*e4b17023SJohn Marino 				PASS_MEM_STAT);
465*e4b17023SJohn Marino }
466*e4b17023SJohn Marino 
467*e4b17023SJohn Marino /* Exact version of vec_stack_p_reserve.  */
468*e4b17023SJohn Marino 
469*e4b17023SJohn Marino void *
vec_stack_p_reserve_exact(void * vec,int reserve MEM_STAT_DECL)470*e4b17023SJohn Marino vec_stack_p_reserve_exact (void *vec, int reserve MEM_STAT_DECL)
471*e4b17023SJohn Marino {
472*e4b17023SJohn Marino   return vec_stack_o_reserve_1 (vec, reserve,
473*e4b17023SJohn Marino 				sizeof (struct vec_prefix),
474*e4b17023SJohn Marino 				sizeof (void *), true
475*e4b17023SJohn Marino 				PASS_MEM_STAT);
476*e4b17023SJohn Marino }
477*e4b17023SJohn Marino 
478*e4b17023SJohn Marino /* Like vec_stack_p_reserve, but for objects.  */
479*e4b17023SJohn Marino 
480*e4b17023SJohn Marino void *
vec_stack_o_reserve(void * vec,int reserve,size_t vec_offset,size_t elt_size MEM_STAT_DECL)481*e4b17023SJohn Marino vec_stack_o_reserve (void *vec, int reserve, size_t vec_offset,
482*e4b17023SJohn Marino 		     size_t elt_size MEM_STAT_DECL)
483*e4b17023SJohn Marino {
484*e4b17023SJohn Marino   return vec_stack_o_reserve_1 (vec, reserve, vec_offset, elt_size, false
485*e4b17023SJohn Marino 				PASS_MEM_STAT);
486*e4b17023SJohn Marino }
487*e4b17023SJohn Marino 
488*e4b17023SJohn Marino /* Like vec_stack_p_reserve_exact, but for objects.  */
489*e4b17023SJohn Marino 
490*e4b17023SJohn Marino void *
vec_stack_o_reserve_exact(void * vec,int reserve,size_t vec_offset,size_t elt_size MEM_STAT_DECL)491*e4b17023SJohn Marino vec_stack_o_reserve_exact (void *vec, int reserve, size_t vec_offset,
492*e4b17023SJohn Marino 			    size_t elt_size MEM_STAT_DECL)
493*e4b17023SJohn Marino {
494*e4b17023SJohn Marino   return vec_stack_o_reserve_1 (vec, reserve, vec_offset, elt_size, true
495*e4b17023SJohn Marino 				PASS_MEM_STAT);
496*e4b17023SJohn Marino }
497*e4b17023SJohn Marino 
498*e4b17023SJohn Marino /* Free a vector allocated on the stack.  Don't actually free it if we
499*e4b17023SJohn Marino    find it in the hash table.  */
500*e4b17023SJohn Marino 
501*e4b17023SJohn Marino void
vec_stack_free(void * vec)502*e4b17023SJohn Marino vec_stack_free (void *vec)
503*e4b17023SJohn Marino {
504*e4b17023SJohn Marino   unsigned int ix;
505*e4b17023SJohn Marino 
506*e4b17023SJohn Marino   for (ix = VEC_length (void_p, stack_vecs); ix > 0; --ix)
507*e4b17023SJohn Marino     {
508*e4b17023SJohn Marino       if (VEC_index (void_p, stack_vecs, ix - 1) == vec)
509*e4b17023SJohn Marino 	{
510*e4b17023SJohn Marino 	  VEC_unordered_remove (void_p, stack_vecs, ix - 1);
511*e4b17023SJohn Marino 	  return;
512*e4b17023SJohn Marino 	}
513*e4b17023SJohn Marino     }
514*e4b17023SJohn Marino 
515*e4b17023SJohn Marino   /* VEC was not on the list of vecs allocated on the stack, so it
516*e4b17023SJohn Marino      must be allocated on the heap.  */
517*e4b17023SJohn Marino   vec_heap_free (vec);
518*e4b17023SJohn Marino }
519*e4b17023SJohn Marino 
520*e4b17023SJohn Marino #if ENABLE_CHECKING
521*e4b17023SJohn Marino /* Issue a vector domain error, and then fall over.  */
522*e4b17023SJohn Marino 
523*e4b17023SJohn Marino void
vec_assert_fail(const char * op,const char * struct_name,const char * file,unsigned int line,const char * function)524*e4b17023SJohn Marino vec_assert_fail (const char *op, const char *struct_name,
525*e4b17023SJohn Marino 		 const char *file, unsigned int line, const char *function)
526*e4b17023SJohn Marino {
527*e4b17023SJohn Marino   internal_error ("vector %s %s domain error, in %s at %s:%u",
528*e4b17023SJohn Marino 		  struct_name, op, function, trim_filename (file), line);
529*e4b17023SJohn Marino }
530*e4b17023SJohn Marino #endif
531*e4b17023SJohn Marino 
532*e4b17023SJohn Marino #ifdef GATHER_STATISTICS
533*e4b17023SJohn Marino /* Helper for qsort; sort descriptors by amount of memory consumed.  */
534*e4b17023SJohn Marino static int
cmp_statistic(const void * loc1,const void * loc2)535*e4b17023SJohn Marino cmp_statistic (const void *loc1, const void *loc2)
536*e4b17023SJohn Marino {
537*e4b17023SJohn Marino   const struct vec_descriptor *const l1 =
538*e4b17023SJohn Marino     *(const struct vec_descriptor *const *) loc1;
539*e4b17023SJohn Marino   const struct vec_descriptor *const l2 =
540*e4b17023SJohn Marino     *(const struct vec_descriptor *const *) loc2;
541*e4b17023SJohn Marino   long diff;
542*e4b17023SJohn Marino   diff = l1->allocated - l2->allocated;
543*e4b17023SJohn Marino   if (!diff)
544*e4b17023SJohn Marino     diff = l1->peak - l2->peak;
545*e4b17023SJohn Marino   if (!diff)
546*e4b17023SJohn Marino     diff = l1->times - l2->times;
547*e4b17023SJohn Marino   return diff > 0 ? 1 : diff < 0 ? -1 : 0;
548*e4b17023SJohn Marino }
549*e4b17023SJohn Marino /* Collect array of the descriptors from hashtable.  */
550*e4b17023SJohn Marino static struct vec_descriptor **loc_array;
551*e4b17023SJohn Marino static int
add_statistics(void ** slot,void * b)552*e4b17023SJohn Marino add_statistics (void **slot, void *b)
553*e4b17023SJohn Marino {
554*e4b17023SJohn Marino   int *n = (int *)b;
555*e4b17023SJohn Marino   loc_array[*n] = (struct vec_descriptor *) *slot;
556*e4b17023SJohn Marino   (*n)++;
557*e4b17023SJohn Marino   return 1;
558*e4b17023SJohn Marino }
559*e4b17023SJohn Marino 
560*e4b17023SJohn Marino /* Dump per-site memory statistics.  */
561*e4b17023SJohn Marino #endif
562*e4b17023SJohn Marino void
dump_vec_loc_statistics(void)563*e4b17023SJohn Marino dump_vec_loc_statistics (void)
564*e4b17023SJohn Marino {
565*e4b17023SJohn Marino #ifdef GATHER_STATISTICS
566*e4b17023SJohn Marino   int nentries = 0;
567*e4b17023SJohn Marino   char s[4096];
568*e4b17023SJohn Marino   size_t allocated = 0;
569*e4b17023SJohn Marino   size_t times = 0;
570*e4b17023SJohn Marino   int i;
571*e4b17023SJohn Marino 
572*e4b17023SJohn Marino   loc_array = XCNEWVEC (struct vec_descriptor *, vec_desc_hash->n_elements);
573*e4b17023SJohn Marino   fprintf (stderr, "Heap vectors:\n");
574*e4b17023SJohn Marino   fprintf (stderr, "\n%-48s %10s       %10s       %10s\n",
575*e4b17023SJohn Marino 	   "source location", "Leak", "Peak", "Times");
576*e4b17023SJohn Marino   fprintf (stderr, "-------------------------------------------------------\n");
577*e4b17023SJohn Marino   htab_traverse (vec_desc_hash, add_statistics, &nentries);
578*e4b17023SJohn Marino   qsort (loc_array, nentries, sizeof (*loc_array), cmp_statistic);
579*e4b17023SJohn Marino   for (i = 0; i < nentries; i++)
580*e4b17023SJohn Marino     {
581*e4b17023SJohn Marino       struct vec_descriptor *d = loc_array[i];
582*e4b17023SJohn Marino       allocated += d->allocated;
583*e4b17023SJohn Marino       times += d->times;
584*e4b17023SJohn Marino     }
585*e4b17023SJohn Marino   for (i = 0; i < nentries; i++)
586*e4b17023SJohn Marino     {
587*e4b17023SJohn Marino       struct vec_descriptor *d = loc_array[i];
588*e4b17023SJohn Marino       const char *s1 = d->file;
589*e4b17023SJohn Marino       const char *s2;
590*e4b17023SJohn Marino       while ((s2 = strstr (s1, "gcc/")))
591*e4b17023SJohn Marino 	s1 = s2 + 4;
592*e4b17023SJohn Marino       sprintf (s, "%s:%i (%s)", s1, d->line, d->function);
593*e4b17023SJohn Marino       s[48] = 0;
594*e4b17023SJohn Marino       fprintf (stderr, "%-48s %10li:%4.1f%% %10li      %10li:%4.1f%% \n", s,
595*e4b17023SJohn Marino 	       (long)d->allocated,
596*e4b17023SJohn Marino 	       (d->allocated) * 100.0 / allocated,
597*e4b17023SJohn Marino 	       (long)d->peak,
598*e4b17023SJohn Marino 	       (long)d->times,
599*e4b17023SJohn Marino 	       (d->times) * 100.0 / times);
600*e4b17023SJohn Marino     }
601*e4b17023SJohn Marino   fprintf (stderr, "%-48s %10ld                        %10ld\n",
602*e4b17023SJohn Marino 	   "Total", (long)allocated, (long)times);
603*e4b17023SJohn Marino   fprintf (stderr, "\n%-48s %10s       %10s       %10s\n",
604*e4b17023SJohn Marino 	   "source location", "Leak", "Peak", "Times");
605*e4b17023SJohn Marino   fprintf (stderr, "-------------------------------------------------------\n");
606*e4b17023SJohn Marino #endif
607*e4b17023SJohn Marino }
608