1 /* Vector API for GNU compiler.
2 Copyright (C) 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
3 Contributed by Nathan Sidwell <nathan@codesourcery.com>
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 /* This file is compiled twice: once for the generator programs
22 once for the compiler. */
32 #include "coretypes.h"
33 #include "diagnostic-core.h"
44 #ifdef GATHER_STATISTICS
46 /* Store information about each particular vector. */
58 /* Hashtable mapping vec addresses to descriptors. */
59 static htab_t vec_desc_hash
;
61 /* Hashtable helpers. */
63 hash_descriptor (const void *p
)
65 const struct vec_descriptor
*const d
=
66 (const struct vec_descriptor
*) p
;
67 return htab_hash_pointer (d
->file
) + d
->line
;
70 eq_descriptor (const void *p1
, const void *p2
)
72 const struct vec_descriptor
*const d
= (const struct vec_descriptor
*) p1
;
73 const struct vec_descriptor
*const l
= (const struct vec_descriptor
*) p2
;
74 return d
->file
== l
->file
&& d
->function
== l
->function
&& d
->line
== l
->line
;
77 /* Hashtable converting address of allocated field to loc descriptor. */
78 static htab_t ptr_hash
;
82 struct vec_descriptor
*loc
;
86 /* Hash table helpers functions. */
88 hash_ptr (const void *p
)
90 const struct ptr_hash_entry
*const d
= (const struct ptr_hash_entry
*) p
;
92 return htab_hash_pointer (d
->ptr
);
96 eq_ptr (const void *p1
, const void *p2
)
98 const struct ptr_hash_entry
*const p
= (const struct ptr_hash_entry
*) p1
;
100 return (p
->ptr
== p2
);
103 /* Return descriptor for given call site, create new one if needed. */
104 static struct vec_descriptor
*
105 vec_descriptor (const char *name
, int line
, const char *function
)
107 struct vec_descriptor loc
;
108 struct vec_descriptor
**slot
;
112 loc
.function
= function
;
114 vec_desc_hash
= htab_create (10, hash_descriptor
, eq_descriptor
, NULL
);
116 slot
= (struct vec_descriptor
**) htab_find_slot (vec_desc_hash
, &loc
,
120 *slot
= XCNEW (struct vec_descriptor
);
121 (*slot
)->file
= name
;
122 (*slot
)->line
= line
;
123 (*slot
)->function
= function
;
124 (*slot
)->allocated
= 0;
129 /* Account the overhead. */
131 register_overhead (struct vec_prefix
*ptr
, size_t size
,
132 const char *name
, int line
, const char *function
)
134 struct vec_descriptor
*loc
= vec_descriptor (name
, line
, function
);
135 struct ptr_hash_entry
*p
= XNEW (struct ptr_hash_entry
);
142 ptr_hash
= htab_create (10, hash_ptr
, eq_ptr
, NULL
);
143 slot
= htab_find_slot_with_hash (ptr_hash
, ptr
, htab_hash_pointer (ptr
), INSERT
);
147 loc
->allocated
+= size
;
148 if (loc
->peak
< loc
->allocated
)
149 loc
->peak
+= loc
->allocated
;
153 /* Notice that the pointer has been freed. */
155 free_overhead (struct vec_prefix
*ptr
)
157 PTR
*slot
= htab_find_slot_with_hash (ptr_hash
, ptr
, htab_hash_pointer (ptr
),
159 struct ptr_hash_entry
*p
= (struct ptr_hash_entry
*) *slot
;
160 p
->loc
->allocated
-= p
->allocated
;
161 htab_clear_slot (ptr_hash
, slot
);
166 vec_heap_free (void *ptr
)
168 free_overhead ((struct vec_prefix
*)ptr
);
173 /* Calculate the new ALLOC value, making sure that RESERVE slots are
174 free. If EXACT grow exactly, otherwise grow exponentially. */
176 static inline unsigned
177 calculate_allocation (const struct vec_prefix
*pfx
, int reserve
, bool exact
)
182 gcc_assert (reserve
>= 0);
190 /* If there's no prefix, and we've not requested anything, then we
191 will create a NULL vector. */
194 /* We must have run out of room. */
195 gcc_assert (alloc
- num
< (unsigned) reserve
);
199 alloc
= num
+ reserve
;
202 /* Exponential growth. */
206 /* Double when small. */
209 /* Grow slower when large. */
210 alloc
= (alloc
* 3 / 2);
212 /* If this is still too small, set it to the right size. */
213 if (alloc
< num
+ reserve
)
214 alloc
= num
+ reserve
;
219 /* Ensure there are at least RESERVE free slots in VEC. If EXACT grow
220 exactly, else grow exponentially. As a special case, if VEC is
221 NULL and RESERVE is 0, no vector will be created. The vector's
222 trailing array is at VEC_OFFSET offset and consists of ELT_SIZE
226 vec_gc_o_reserve_1 (void *vec
, int reserve
, size_t vec_offset
, size_t elt_size
,
227 bool exact MEM_STAT_DECL
)
229 struct vec_prefix
*pfx
= (struct vec_prefix
*) vec
;
230 unsigned alloc
= calculate_allocation (pfx
, reserve
, exact
);
239 vec
= ggc_realloc_stat (vec
, vec_offset
+ alloc
* elt_size PASS_MEM_STAT
);
240 ((struct vec_prefix
*)vec
)->alloc
= alloc
;
242 ((struct vec_prefix
*)vec
)->num
= 0;
247 /* Ensure there are at least RESERVE free slots in VEC, growing
248 exponentially. If RESERVE < 0 grow exactly, else grow
249 exponentially. As a special case, if VEC is NULL, and RESERVE is
250 0, no vector will be created. */
253 vec_gc_p_reserve (void *vec
, int reserve MEM_STAT_DECL
)
255 return vec_gc_o_reserve_1 (vec
, reserve
,
256 offsetof (struct vec_prefix
, vec
),
257 sizeof (void *), false
261 /* Ensure there are at least RESERVE free slots in VEC, growing
262 exactly. If RESERVE < 0 grow exactly, else grow exponentially. As
263 a special case, if VEC is NULL, and RESERVE is 0, no vector will be
267 vec_gc_p_reserve_exact (void *vec
, int reserve MEM_STAT_DECL
)
269 return vec_gc_o_reserve_1 (vec
, reserve
,
270 offsetof (struct vec_prefix
, vec
),
271 sizeof (void *), true
275 /* As for vec_gc_p_reserve, but for object vectors. The vector's
276 trailing array is at VEC_OFFSET offset and consists of ELT_SIZE
280 vec_gc_o_reserve (void *vec
, int reserve
, size_t vec_offset
, size_t elt_size
283 return vec_gc_o_reserve_1 (vec
, reserve
, vec_offset
, elt_size
, false
287 /* As for vec_gc_p_reserve_exact, but for object vectors. The
288 vector's trailing array is at VEC_OFFSET offset and consists of
289 ELT_SIZE sized elements. */
292 vec_gc_o_reserve_exact (void *vec
, int reserve
, size_t vec_offset
,
293 size_t elt_size MEM_STAT_DECL
)
295 return vec_gc_o_reserve_1 (vec
, reserve
, vec_offset
, elt_size
, true
299 /* As for vec_gc_o_reserve_1, but for heap allocated vectors. */
302 vec_heap_o_reserve_1 (void *vec
, int reserve
, size_t vec_offset
,
303 size_t elt_size
, bool exact MEM_STAT_DECL
)
305 struct vec_prefix
*pfx
= (struct vec_prefix
*) vec
;
306 unsigned alloc
= calculate_allocation (pfx
, reserve
, exact
);
315 #ifdef GATHER_STATISTICS
320 vec
= xrealloc (vec
, vec_offset
+ alloc
* elt_size
);
321 ((struct vec_prefix
*)vec
)->alloc
= alloc
;
323 ((struct vec_prefix
*)vec
)->num
= 0;
324 #ifdef GATHER_STATISTICS
326 register_overhead ((struct vec_prefix
*)vec
,
327 vec_offset
+ alloc
* elt_size PASS_MEM_STAT
);
333 /* As for vec_gc_p_reserve, but for heap allocated vectors. */
336 vec_heap_p_reserve (void *vec
, int reserve MEM_STAT_DECL
)
338 return vec_heap_o_reserve_1 (vec
, reserve
,
339 offsetof (struct vec_prefix
, vec
),
340 sizeof (void *), false
344 /* As for vec_gc_p_reserve_exact, but for heap allocated vectors. */
347 vec_heap_p_reserve_exact (void *vec
, int reserve MEM_STAT_DECL
)
349 return vec_heap_o_reserve_1 (vec
, reserve
,
350 offsetof (struct vec_prefix
, vec
),
351 sizeof (void *), true
355 /* As for vec_gc_o_reserve, but for heap allocated vectors. */
358 vec_heap_o_reserve (void *vec
, int reserve
, size_t vec_offset
, size_t elt_size
361 return vec_heap_o_reserve_1 (vec
, reserve
, vec_offset
, elt_size
, false
365 /* As for vec_gc_o_reserve_exact, but for heap allocated vectors. */
368 vec_heap_o_reserve_exact (void *vec
, int reserve
, size_t vec_offset
,
369 size_t elt_size MEM_STAT_DECL
)
371 return vec_heap_o_reserve_1 (vec
, reserve
, vec_offset
, elt_size
, true
375 /* Stack vectors are a little different. VEC_alloc turns into a call
376 to vec_stack_p_reserve_exact1 and passes in space allocated via a
377 call to alloca. We record that pointer so that we know that we
378 shouldn't free it. If the vector is resized, we resize it on the
379 heap. We record the pointers in a vector and search it in LIFO
380 order--i.e., we look for the newest stack vectors first. We don't
381 expect too many stack vectors at any one level, and searching from
382 the end should normally be efficient even if they are used in a
383 recursive function. */
385 typedef void *void_p
;
387 DEF_VEC_ALLOC_P(void_p
,heap
);
389 static VEC(void_p
,heap
) *stack_vecs
;
391 /* Allocate a vector which uses alloca for the initial allocation.
392 SPACE is space allocated using alloca, ALLOC is the number of
393 entries allocated. */
396 vec_stack_p_reserve_exact_1 (int alloc
, void *space
)
398 struct vec_prefix
*pfx
= (struct vec_prefix
*) space
;
400 VEC_safe_push (void_p
, heap
, stack_vecs
, space
);
408 /* Grow a vector allocated using alloca. When this happens, we switch
409 back to heap allocation. We remove the vector from stack_vecs, if
410 it is there, since we no longer need to avoid freeing it. */
413 vec_stack_o_reserve_1 (void *vec
, int reserve
, size_t vec_offset
,
414 size_t elt_size
, bool exact MEM_STAT_DECL
)
421 for (ix
= VEC_length (void_p
, stack_vecs
); ix
> 0; --ix
)
423 if (VEC_index (void_p
, stack_vecs
, ix
- 1) == vec
)
425 VEC_unordered_remove (void_p
, stack_vecs
, ix
- 1);
433 /* VEC is already on the heap. */
434 return vec_heap_o_reserve_1 (vec
, reserve
, vec_offset
, elt_size
,
435 exact PASS_MEM_STAT
);
438 /* Move VEC to the heap. */
439 reserve
+= ((struct vec_prefix
*) vec
)->num
;
440 newvec
= vec_heap_o_reserve_1 (NULL
, reserve
, vec_offset
, elt_size
,
441 exact PASS_MEM_STAT
);
444 ((struct vec_prefix
*) newvec
)->num
= ((struct vec_prefix
*) vec
)->num
;
445 memcpy (((struct vec_prefix
*) newvec
)->vec
,
446 ((struct vec_prefix
*) vec
)->vec
,
447 ((struct vec_prefix
*) vec
)->num
* elt_size
);
452 /* Grow a vector allocated on the stack. */
455 vec_stack_p_reserve (void *vec
, int reserve MEM_STAT_DECL
)
457 return vec_stack_o_reserve_1 (vec
, reserve
,
458 offsetof (struct vec_prefix
, vec
),
459 sizeof (void *), false
463 /* Exact version of vec_stack_p_reserve. */
466 vec_stack_p_reserve_exact (void *vec
, int reserve MEM_STAT_DECL
)
468 return vec_stack_o_reserve_1 (vec
, reserve
,
469 offsetof (struct vec_prefix
, vec
),
470 sizeof (void *), true
474 /* Like vec_stack_p_reserve, but for objects. */
477 vec_stack_o_reserve (void *vec
, int reserve
, size_t vec_offset
,
478 size_t elt_size MEM_STAT_DECL
)
480 return vec_stack_o_reserve_1 (vec
, reserve
, vec_offset
, elt_size
, false
484 /* Like vec_stack_p_reserve_exact, but for objects. */
487 vec_stack_o_reserve_exact (void *vec
, int reserve
, size_t vec_offset
,
488 size_t elt_size MEM_STAT_DECL
)
490 return vec_stack_o_reserve_1 (vec
, reserve
, vec_offset
, elt_size
, true
494 /* Free a vector allocated on the stack. Don't actually free it if we
495 find it in the hash table. */
498 vec_stack_free (void *vec
)
502 for (ix
= VEC_length (void_p
, stack_vecs
); ix
> 0; --ix
)
504 if (VEC_index (void_p
, stack_vecs
, ix
- 1) == vec
)
506 VEC_unordered_remove (void_p
, stack_vecs
, ix
- 1);
511 /* VEC was not on the list of vecs allocated on the stack, so it
512 must be allocated on the heap. */
517 /* Issue a vector domain error, and then fall over. */
520 vec_assert_fail (const char *op
, const char *struct_name
,
521 const char *file
, unsigned int line
, const char *function
)
523 internal_error ("vector %s %s domain error, in %s at %s:%u",
524 struct_name
, op
, function
, trim_filename (file
), line
);
528 #ifdef GATHER_STATISTICS
529 /* Helper for qsort; sort descriptors by amount of memory consumed. */
531 cmp_statistic (const void *loc1
, const void *loc2
)
533 const struct vec_descriptor
*const l1
=
534 *(const struct vec_descriptor
*const *) loc1
;
535 const struct vec_descriptor
*const l2
=
536 *(const struct vec_descriptor
*const *) loc2
;
538 diff
= l1
->allocated
- l2
->allocated
;
540 diff
= l1
->peak
- l2
->peak
;
542 diff
= l1
->times
- l2
->times
;
543 return diff
> 0 ? 1 : diff
< 0 ? -1 : 0;
545 /* Collect array of the descriptors from hashtable. */
546 static struct vec_descriptor
**loc_array
;
548 add_statistics (void **slot
, void *b
)
551 loc_array
[*n
] = (struct vec_descriptor
*) *slot
;
556 /* Dump per-site memory statistics. */
559 dump_vec_loc_statistics (void)
561 #ifdef GATHER_STATISTICS
564 size_t allocated
= 0;
568 loc_array
= XCNEWVEC (struct vec_descriptor
*, vec_desc_hash
->n_elements
);
569 fprintf (stderr
, "Heap vectors:\n");
570 fprintf (stderr
, "\n%-48s %10s %10s %10s\n",
571 "source location", "Leak", "Peak", "Times");
572 fprintf (stderr
, "-------------------------------------------------------\n");
573 htab_traverse (vec_desc_hash
, add_statistics
, &nentries
);
574 qsort (loc_array
, nentries
, sizeof (*loc_array
), cmp_statistic
);
575 for (i
= 0; i
< nentries
; i
++)
577 struct vec_descriptor
*d
= loc_array
[i
];
578 allocated
+= d
->allocated
;
581 for (i
= 0; i
< nentries
; i
++)
583 struct vec_descriptor
*d
= loc_array
[i
];
584 const char *s1
= d
->file
;
586 while ((s2
= strstr (s1
, "gcc/")))
588 sprintf (s
, "%s:%i (%s)", s1
, d
->line
, d
->function
);
590 fprintf (stderr
, "%-48s %10li:%4.1f%% %10li %10li:%4.1f%% \n", s
,
592 (d
->allocated
) * 100.0 / allocated
,
595 (d
->times
) * 100.0 / times
);
597 fprintf (stderr
, "%-48s %10ld %10ld\n",
598 "Total", (long)allocated
, (long)times
);
599 fprintf (stderr
, "\n%-48s %10s %10s %10s\n",
600 "source location", "Leak", "Peak", "Times");
601 fprintf (stderr
, "-------------------------------------------------------\n");