1 /* Vector API for GNU compiler.
2 Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010
3 Free Software Foundation, Inc.
4 Contributed by Nathan Sidwell <nathan@codesourcery.com>
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
22 /* This file is compiled twice: once for the generator programs
23 once for the compiler. */
31 #include "coretypes.h"
34 #include "diagnostic-core.h"
37 #ifdef GATHER_STATISTICS
39 /* Store information about each particular vector. */
51 /* Hashtable mapping vec addresses to descriptors. */
52 static htab_t vec_desc_hash
;
54 /* Hashtable helpers. */
56 hash_descriptor (const void *p
)
58 const struct vec_descriptor
*const d
=
59 (const struct vec_descriptor
*) p
;
60 return htab_hash_pointer (d
->file
) + d
->line
;
63 eq_descriptor (const void *p1
, const void *p2
)
65 const struct vec_descriptor
*const d
= (const struct vec_descriptor
*) p1
;
66 const struct vec_descriptor
*const l
= (const struct vec_descriptor
*) p2
;
67 return d
->file
== l
->file
&& d
->function
== l
->function
&& d
->line
== l
->line
;
70 /* Hashtable converting address of allocated field to loc descriptor. */
71 static htab_t ptr_hash
;
75 struct vec_descriptor
*loc
;
79 /* Hash table helpers functions. */
81 hash_ptr (const void *p
)
83 const struct ptr_hash_entry
*const d
= (const struct ptr_hash_entry
*) p
;
85 return htab_hash_pointer (d
->ptr
);
89 eq_ptr (const void *p1
, const void *p2
)
91 const struct ptr_hash_entry
*const p
= (const struct ptr_hash_entry
*) p1
;
93 return (p
->ptr
== p2
);
96 /* Return descriptor for given call site, create new one if needed. */
97 static struct vec_descriptor
*
98 vec_descriptor (const char *name
, int line
, const char *function
)
100 struct vec_descriptor loc
;
101 struct vec_descriptor
**slot
;
105 loc
.function
= function
;
107 vec_desc_hash
= htab_create (10, hash_descriptor
, eq_descriptor
, NULL
);
109 slot
= (struct vec_descriptor
**) htab_find_slot (vec_desc_hash
, &loc
,
113 *slot
= XCNEW (struct vec_descriptor
);
114 (*slot
)->file
= name
;
115 (*slot
)->line
= line
;
116 (*slot
)->function
= function
;
117 (*slot
)->allocated
= 0;
122 /* Account the overhead. */
124 register_overhead (struct vec_prefix
*ptr
, size_t size
,
125 const char *name
, int line
, 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
, ptr
, htab_hash_pointer (ptr
), INSERT
);
140 loc
->allocated
+= size
;
141 if (loc
->peak
< loc
->allocated
)
142 loc
->peak
+= loc
->allocated
;
146 /* Notice that the pointer has been freed. */
148 free_overhead (struct vec_prefix
*ptr
)
150 PTR
*slot
= htab_find_slot_with_hash (ptr_hash
, ptr
, htab_hash_pointer (ptr
),
152 struct ptr_hash_entry
*p
= (struct ptr_hash_entry
*) *slot
;
153 p
->loc
->allocated
-= p
->allocated
;
154 htab_clear_slot (ptr_hash
, slot
);
159 vec_heap_free (void *ptr
)
161 free_overhead ((struct vec_prefix
*)ptr
);
166 /* Calculate the new ALLOC value, making sure that RESERVE slots are
167 free. If EXACT grow exactly, otherwise grow exponentially. */
169 static inline unsigned
170 calculate_allocation (const struct vec_prefix
*pfx
, int reserve
, bool exact
)
175 gcc_assert (reserve
>= 0);
183 /* If there's no prefix, and we've not requested anything, then we
184 will create a NULL vector. */
187 /* We must have run out of room. */
188 gcc_assert (alloc
- num
< (unsigned) reserve
);
192 alloc
= num
+ reserve
;
195 /* Exponential growth. */
199 /* Double when small. */
202 /* Grow slower when large. */
203 alloc
= (alloc
* 3 / 2);
205 /* If this is still too small, set it to the right size. */
206 if (alloc
< num
+ reserve
)
207 alloc
= num
+ reserve
;
212 /* Ensure there are at least RESERVE free slots in VEC. If EXACT grow
213 exactly, else grow exponentially. As a special case, if VEC is
214 NULL and RESERVE is 0, no vector will be created. The vector's
215 trailing array is at VEC_OFFSET offset and consists of ELT_SIZE
219 vec_gc_o_reserve_1 (void *vec
, int reserve
, size_t vec_offset
, size_t elt_size
,
220 bool exact MEM_STAT_DECL
)
222 struct vec_prefix
*pfx
= (struct vec_prefix
*) vec
;
223 unsigned alloc
= calculate_allocation (pfx
, reserve
, exact
);
232 vec
= ggc_realloc_stat (vec
, vec_offset
+ alloc
* elt_size PASS_MEM_STAT
);
233 ((struct vec_prefix
*)vec
)->alloc
= alloc
;
235 ((struct vec_prefix
*)vec
)->num
= 0;
240 /* Ensure there are at least RESERVE free slots in VEC, growing
241 exponentially. If RESERVE < 0 grow exactly, else grow
242 exponentially. As a special case, if VEC is NULL, and RESERVE is
243 0, no vector will be created. */
246 vec_gc_p_reserve (void *vec
, int reserve MEM_STAT_DECL
)
248 return vec_gc_o_reserve_1 (vec
, reserve
,
249 sizeof (struct vec_prefix
),
250 sizeof (void *), false
254 /* Ensure there are at least RESERVE free slots in VEC, growing
255 exactly. If RESERVE < 0 grow exactly, else grow exponentially. As
256 a special case, if VEC is NULL, and RESERVE is 0, no vector will be
260 vec_gc_p_reserve_exact (void *vec
, int reserve MEM_STAT_DECL
)
262 return vec_gc_o_reserve_1 (vec
, reserve
,
263 sizeof (struct vec_prefix
),
264 sizeof (void *), true
268 /* As for vec_gc_p_reserve, but for object vectors. The vector's
269 trailing array is at VEC_OFFSET offset and consists of ELT_SIZE
273 vec_gc_o_reserve (void *vec
, int reserve
, size_t vec_offset
, size_t elt_size
276 return vec_gc_o_reserve_1 (vec
, reserve
, vec_offset
, elt_size
, false
280 /* As for vec_gc_p_reserve_exact, but for object vectors. The
281 vector's trailing array is at VEC_OFFSET offset and consists of
282 ELT_SIZE sized elements. */
285 vec_gc_o_reserve_exact (void *vec
, int reserve
, size_t vec_offset
,
286 size_t elt_size MEM_STAT_DECL
)
288 return vec_gc_o_reserve_1 (vec
, reserve
, vec_offset
, elt_size
, true
292 /* As for vec_gc_o_reserve_1, but for heap allocated vectors. */
295 vec_heap_o_reserve_1 (void *vec
, int reserve
, size_t vec_offset
,
296 size_t elt_size
, bool exact MEM_STAT_DECL
)
298 struct vec_prefix
*pfx
= (struct vec_prefix
*) vec
;
299 unsigned alloc
= calculate_allocation (pfx
, reserve
, exact
);
308 #ifdef GATHER_STATISTICS
313 vec
= xrealloc (vec
, vec_offset
+ alloc
* elt_size
);
314 ((struct vec_prefix
*)vec
)->alloc
= alloc
;
316 ((struct vec_prefix
*)vec
)->num
= 0;
317 #ifdef GATHER_STATISTICS
319 register_overhead ((struct vec_prefix
*)vec
,
320 vec_offset
+ alloc
* elt_size PASS_MEM_STAT
);
326 /* As for vec_gc_p_reserve, but for heap allocated vectors. */
329 vec_heap_p_reserve (void *vec
, int reserve MEM_STAT_DECL
)
331 return vec_heap_o_reserve_1 (vec
, reserve
,
332 sizeof (struct vec_prefix
),
333 sizeof (void *), false
337 /* As for vec_gc_p_reserve_exact, but for heap allocated vectors. */
340 vec_heap_p_reserve_exact (void *vec
, int reserve MEM_STAT_DECL
)
342 return vec_heap_o_reserve_1 (vec
, reserve
,
343 sizeof (struct vec_prefix
),
344 sizeof (void *), true
348 /* As for vec_gc_o_reserve, but for heap allocated vectors. */
351 vec_heap_o_reserve (void *vec
, int reserve
, size_t vec_offset
, size_t elt_size
354 return vec_heap_o_reserve_1 (vec
, reserve
, vec_offset
, elt_size
, false
358 /* As for vec_gc_o_reserve_exact, but for heap allocated vectors. */
361 vec_heap_o_reserve_exact (void *vec
, int reserve
, size_t vec_offset
,
362 size_t elt_size MEM_STAT_DECL
)
364 return vec_heap_o_reserve_1 (vec
, reserve
, vec_offset
, elt_size
, true
368 /* Stack vectors are a little different. VEC_alloc turns into a call
369 to vec_stack_p_reserve_exact1 and passes in space allocated via a
370 call to alloca. We record that pointer so that we know that we
371 shouldn't free it. If the vector is resized, we resize it on the
372 heap. We record the pointers in a vector and search it in LIFO
373 order--i.e., we look for the newest stack vectors first. We don't
374 expect too many stack vectors at any one level, and searching from
375 the end should normally be efficient even if they are used in a
376 recursive function. */
378 typedef void *void_p
;
380 DEF_VEC_ALLOC_P(void_p
,heap
);
382 static VEC(void_p
,heap
) *stack_vecs
;
384 /* Allocate a vector which uses alloca for the initial allocation.
385 SPACE is space allocated using alloca, ALLOC is the number of
386 entries allocated. */
389 vec_stack_p_reserve_exact_1 (int alloc
, void *space
)
391 struct vec_prefix
*pfx
= (struct vec_prefix
*) space
;
393 VEC_safe_push (void_p
, heap
, stack_vecs
, space
);
401 /* Grow a vector allocated using alloca. When this happens, we switch
402 back to heap allocation. We remove the vector from stack_vecs, if
403 it is there, since we no longer need to avoid freeing it. */
406 vec_stack_o_reserve_1 (void *vec
, int reserve
, size_t vec_offset
,
407 size_t elt_size
, bool exact MEM_STAT_DECL
)
414 for (ix
= VEC_length (void_p
, stack_vecs
); ix
> 0; --ix
)
416 if (VEC_index (void_p
, stack_vecs
, ix
- 1) == vec
)
418 VEC_unordered_remove (void_p
, stack_vecs
, ix
- 1);
426 /* VEC is already on the heap. */
427 return vec_heap_o_reserve_1 (vec
, reserve
, vec_offset
, elt_size
,
428 exact PASS_MEM_STAT
);
431 /* Move VEC to the heap. */
432 reserve
+= ((struct vec_prefix
*) vec
)->num
;
433 newvec
= vec_heap_o_reserve_1 (NULL
, reserve
, vec_offset
, elt_size
,
434 exact PASS_MEM_STAT
);
437 ((struct vec_prefix
*) newvec
)->num
= ((struct vec_prefix
*) vec
)->num
;
438 memcpy (((struct vec_prefix
*) newvec
)+1,
439 ((struct vec_prefix
*) vec
)+1,
440 ((struct vec_prefix
*) vec
)->num
* elt_size
);
445 /* Grow a vector allocated on the stack. */
448 vec_stack_p_reserve (void *vec
, int reserve MEM_STAT_DECL
)
450 return vec_stack_o_reserve_1 (vec
, reserve
,
451 sizeof (struct vec_prefix
),
452 sizeof (void *), false
456 /* Exact version of vec_stack_p_reserve. */
459 vec_stack_p_reserve_exact (void *vec
, int reserve MEM_STAT_DECL
)
461 return vec_stack_o_reserve_1 (vec
, reserve
,
462 sizeof (struct vec_prefix
),
463 sizeof (void *), true
467 /* Like vec_stack_p_reserve, but for objects. */
470 vec_stack_o_reserve (void *vec
, int reserve
, size_t vec_offset
,
471 size_t elt_size MEM_STAT_DECL
)
473 return vec_stack_o_reserve_1 (vec
, reserve
, vec_offset
, elt_size
, false
477 /* Like vec_stack_p_reserve_exact, but for objects. */
480 vec_stack_o_reserve_exact (void *vec
, int reserve
, size_t vec_offset
,
481 size_t elt_size MEM_STAT_DECL
)
483 return vec_stack_o_reserve_1 (vec
, reserve
, vec_offset
, elt_size
, true
487 /* Free a vector allocated on the stack. Don't actually free it if we
488 find it in the hash table. */
491 vec_stack_free (void *vec
)
495 for (ix
= VEC_length (void_p
, stack_vecs
); ix
> 0; --ix
)
497 if (VEC_index (void_p
, stack_vecs
, ix
- 1) == vec
)
499 VEC_unordered_remove (void_p
, stack_vecs
, ix
- 1);
504 /* VEC was not on the list of vecs allocated on the stack, so it
505 must be allocated on the heap. */
510 /* Issue a vector domain error, and then fall over. */
513 vec_assert_fail (const char *op
, const char *struct_name
,
514 const char *file
, unsigned int line
, const char *function
)
516 internal_error ("vector %s %s domain error, in %s at %s:%u",
517 struct_name
, op
, function
, trim_filename (file
), line
);
521 #ifdef GATHER_STATISTICS
522 /* Helper for qsort; sort descriptors by amount of memory consumed. */
524 cmp_statistic (const void *loc1
, const void *loc2
)
526 const struct vec_descriptor
*const l1
=
527 *(const struct vec_descriptor
*const *) loc1
;
528 const struct vec_descriptor
*const l2
=
529 *(const struct vec_descriptor
*const *) loc2
;
531 diff
= l1
->allocated
- l2
->allocated
;
533 diff
= l1
->peak
- l2
->peak
;
535 diff
= l1
->times
- l2
->times
;
536 return diff
> 0 ? 1 : diff
< 0 ? -1 : 0;
538 /* Collect array of the descriptors from hashtable. */
539 static struct vec_descriptor
**loc_array
;
541 add_statistics (void **slot
, void *b
)
544 loc_array
[*n
] = (struct vec_descriptor
*) *slot
;
549 /* Dump per-site memory statistics. */
552 dump_vec_loc_statistics (void)
554 #ifdef GATHER_STATISTICS
557 size_t allocated
= 0;
561 loc_array
= XCNEWVEC (struct vec_descriptor
*, vec_desc_hash
->n_elements
);
562 fprintf (stderr
, "Heap vectors:\n");
563 fprintf (stderr
, "\n%-48s %10s %10s %10s\n",
564 "source location", "Leak", "Peak", "Times");
565 fprintf (stderr
, "-------------------------------------------------------\n");
566 htab_traverse (vec_desc_hash
, add_statistics
, &nentries
);
567 qsort (loc_array
, nentries
, sizeof (*loc_array
), cmp_statistic
);
568 for (i
= 0; i
< nentries
; i
++)
570 struct vec_descriptor
*d
= loc_array
[i
];
571 allocated
+= d
->allocated
;
574 for (i
= 0; i
< nentries
; i
++)
576 struct vec_descriptor
*d
= loc_array
[i
];
577 const char *s1
= d
->file
;
579 while ((s2
= strstr (s1
, "gcc/")))
581 sprintf (s
, "%s:%i (%s)", s1
, d
->line
, d
->function
);
583 fprintf (stderr
, "%-48s %10li:%4.1f%% %10li %10li:%4.1f%% \n", s
,
585 (d
->allocated
) * 100.0 / allocated
,
588 (d
->times
) * 100.0 / times
);
590 fprintf (stderr
, "%-48s %10ld %10ld\n",
591 "Total", (long)allocated
, (long)times
);
592 fprintf (stderr
, "\n%-48s %10s %10s %10s\n",
593 "source location", "Leak", "Peak", "Times");
594 fprintf (stderr
, "-------------------------------------------------------\n");