1 /* Vector API for GNU compiler.
2 Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010, 2011, 2012
3 Free Software Foundation, Inc.
4 Contributed by Nathan Sidwell <nathan@codesourcery.com>
5 Re-implemented in C++ by Diego Novillo <dnovillo@google.com>
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 3, or (at your option) any later
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
23 /* This file is compiled twice: once for the generator programs
24 once for the compiler. */
32 #include "coretypes.h"
35 #include "diagnostic-core.h"
38 /* Store information about each particular vector. */
50 /* Hashtable mapping vec addresses to descriptors. */
51 static htab_t vec_desc_hash
;
53 /* Hashtable helpers. */
55 hash_descriptor (const void *p
)
57 const struct vec_descriptor
*const d
=
58 (const struct vec_descriptor
*) p
;
59 return htab_hash_pointer (d
->file
) + d
->line
;
62 eq_descriptor (const void *p1
, const void *p2
)
64 const struct vec_descriptor
*const d
= (const struct vec_descriptor
*) p1
;
65 const struct vec_descriptor
*const l
= (const struct vec_descriptor
*) p2
;
66 return d
->file
== l
->file
&& d
->function
== l
->function
&& d
->line
== l
->line
;
69 /* Hashtable converting address of allocated field to loc descriptor. */
70 static htab_t ptr_hash
;
74 struct vec_descriptor
*loc
;
78 /* Hash table helpers functions. */
80 hash_ptr (const void *p
)
82 const struct ptr_hash_entry
*const d
= (const struct ptr_hash_entry
*) p
;
84 return htab_hash_pointer (d
->ptr
);
88 eq_ptr (const void *p1
, const void *p2
)
90 const struct ptr_hash_entry
*const p
= (const struct ptr_hash_entry
*) p1
;
92 return (p
->ptr
== p2
);
95 /* Return descriptor for given call site, create new one if needed. */
96 static struct vec_descriptor
*
97 vec_descriptor (const char *name
, int line
, const char *function
)
99 struct vec_descriptor loc
;
100 struct vec_descriptor
**slot
;
104 loc
.function
= function
;
106 vec_desc_hash
= htab_create (10, hash_descriptor
, eq_descriptor
, NULL
);
108 slot
= (struct vec_descriptor
**) htab_find_slot (vec_desc_hash
, &loc
,
112 *slot
= XCNEW (struct vec_descriptor
);
113 (*slot
)->file
= name
;
114 (*slot
)->line
= line
;
115 (*slot
)->function
= function
;
116 (*slot
)->allocated
= 0;
121 /* Account the overhead. */
124 vec_prefix::register_overhead (size_t size
, const char *name
, int line
,
125 const char *function
)
127 struct vec_descriptor
*loc
= vec_descriptor (name
, line
, function
);
128 struct ptr_hash_entry
*p
= XNEW (struct ptr_hash_entry
);
135 ptr_hash
= htab_create (10, hash_ptr
, eq_ptr
, NULL
);
136 slot
= htab_find_slot_with_hash (ptr_hash
, this, htab_hash_pointer (this),
141 loc
->allocated
+= size
;
142 if (loc
->peak
< loc
->allocated
)
143 loc
->peak
+= loc
->allocated
;
148 /* Notice that the memory allocated for the vector has been freed. */
151 vec_prefix::release_overhead (void)
153 PTR
*slot
= htab_find_slot_with_hash (ptr_hash
, this,
154 htab_hash_pointer (this),
156 struct ptr_hash_entry
*p
= (struct ptr_hash_entry
*) *slot
;
157 p
->loc
->allocated
-= p
->allocated
;
158 htab_clear_slot (ptr_hash
, slot
);
163 /* Calculate the number of slots to reserve a vector, making sure that
164 RESERVE slots are free. If EXACT grow exactly, otherwise grow
165 exponentially. PFX is the control data for the vector. */
168 vec_prefix::calculate_allocation (vec_prefix
*pfx
, unsigned reserve
, bool exact
)
179 /* If there's no vector, and we've not requested anything, then we
180 will create a NULL vector. */
183 /* We must have run out of room. */
184 gcc_assert (alloc
- num
< reserve
);
188 alloc
= num
+ reserve
;
191 /* Exponential growth. */
195 /* Double when small. */
198 /* Grow slower when large. */
199 alloc
= (alloc
* 3 / 2);
201 /* If this is still too small, set it to the right size. */
202 if (alloc
< num
+ reserve
)
203 alloc
= num
+ reserve
;
209 /* Stack vectors are a little different. VEC_alloc turns into a call
210 to vec<T, A>::stack_reserve and passes in space allocated via a
211 call to alloca. We record that pointer so that we know that we
212 shouldn't free it. If the vector is resized, we resize it on the
213 heap. We record the pointers in a vector and search it in LIFO
214 order--i.e., we look for the newest stack vectors first. We don't
215 expect too many stack vectors at any one level, and searching from
216 the end should normally be efficient even if they are used in a
217 recursive function. */
219 static vec
<void *> stack_vecs
;
221 /* Add a stack vector to STACK_VECS. */
224 register_stack_vec (void *vec
)
226 stack_vecs
.safe_push (vec
);
230 /* If VEC is registered in STACK_VECS, return its index.
231 Otherwise, return -1. */
234 stack_vec_register_index (void *vec
)
236 for (unsigned ix
= stack_vecs
.length (); ix
> 0; --ix
)
237 if (stack_vecs
[ix
- 1] == vec
)
238 return static_cast<int> (ix
- 1);
243 /* Remove vector at slot IX from the list of registered stack vectors. */
246 unregister_stack_vec (unsigned ix
)
248 stack_vecs
.unordered_remove (ix
);
252 /* Helper for qsort; sort descriptors by amount of memory consumed. */
255 cmp_statistic (const void *loc1
, const void *loc2
)
257 const struct vec_descriptor
*const l1
=
258 *(const struct vec_descriptor
*const *) loc1
;
259 const struct vec_descriptor
*const l2
=
260 *(const struct vec_descriptor
*const *) loc2
;
262 diff
= l1
->allocated
- l2
->allocated
;
264 diff
= l1
->peak
- l2
->peak
;
266 diff
= l1
->times
- l2
->times
;
267 return diff
> 0 ? 1 : diff
< 0 ? -1 : 0;
271 /* Collect array of the descriptors from hashtable. */
273 static struct vec_descriptor
**loc_array
;
275 add_statistics (void **slot
, void *b
)
278 loc_array
[*n
] = (struct vec_descriptor
*) *slot
;
283 /* Dump per-site memory statistics. */
286 dump_vec_loc_statistics (void)
290 size_t allocated
= 0;
294 if (! GATHER_STATISTICS
)
297 loc_array
= XCNEWVEC (struct vec_descriptor
*, vec_desc_hash
->n_elements
);
298 fprintf (stderr
, "Heap vectors:\n");
299 fprintf (stderr
, "\n%-48s %10s %10s %10s\n",
300 "source location", "Leak", "Peak", "Times");
301 fprintf (stderr
, "-------------------------------------------------------\n");
302 htab_traverse (vec_desc_hash
, add_statistics
, &nentries
);
303 qsort (loc_array
, nentries
, sizeof (*loc_array
), cmp_statistic
);
304 for (i
= 0; i
< nentries
; i
++)
306 struct vec_descriptor
*d
= loc_array
[i
];
307 allocated
+= d
->allocated
;
310 for (i
= 0; i
< nentries
; i
++)
312 struct vec_descriptor
*d
= loc_array
[i
];
313 const char *s1
= d
->file
;
315 while ((s2
= strstr (s1
, "gcc/")))
317 sprintf (s
, "%s:%i (%s)", s1
, d
->line
, d
->function
);
319 fprintf (stderr
, "%-48s %10li:%4.1f%% %10li %10li:%4.1f%% \n", s
,
321 (d
->allocated
) * 100.0 / allocated
,
324 (d
->times
) * 100.0 / times
);
326 fprintf (stderr
, "%-48s %10ld %10ld\n",
327 "Total", (long)allocated
, (long)times
);
328 fprintf (stderr
, "\n%-48s %10s %10s %10s\n",
329 "source location", "Leak", "Peak", "Times");
330 fprintf (stderr
, "-------------------------------------------------------\n");