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. */
33 #include "coretypes.h"
34 #include "diagnostic-core.h"
45 #ifdef GATHER_STATISTICS
47 /* Store information about each particular vector. */
59 /* Hashtable mapping vec addresses to descriptors. */
60 static htab_t vec_desc_hash
;
62 /* Hashtable helpers. */
64 hash_descriptor (const void *p
)
66 const struct vec_descriptor
*const d
=
67 (const struct vec_descriptor
*) p
;
68 return htab_hash_pointer (d
->file
) + d
->line
;
71 eq_descriptor (const void *p1
, const void *p2
)
73 const struct vec_descriptor
*const d
= (const struct vec_descriptor
*) p1
;
74 const struct vec_descriptor
*const l
= (const struct vec_descriptor
*) p2
;
75 return d
->file
== l
->file
&& d
->function
== l
->function
&& d
->line
== l
->line
;
78 /* Hashtable converting address of allocated field to loc descriptor. */
79 static htab_t ptr_hash
;
83 struct vec_descriptor
*loc
;
87 /* Hash table helpers functions. */
89 hash_ptr (const void *p
)
91 const struct ptr_hash_entry
*const d
= (const struct ptr_hash_entry
*) p
;
93 return htab_hash_pointer (d
->ptr
);
97 eq_ptr (const void *p1
, const void *p2
)
99 const struct ptr_hash_entry
*const p
= (const struct ptr_hash_entry
*) p1
;
101 return (p
->ptr
== p2
);
104 /* Return descriptor for given call site, create new one if needed. */
105 static struct vec_descriptor
*
106 vec_descriptor (const char *name
, int line
, const char *function
)
108 struct vec_descriptor loc
;
109 struct vec_descriptor
**slot
;
113 loc
.function
= function
;
115 vec_desc_hash
= htab_create (10, hash_descriptor
, eq_descriptor
, NULL
);
117 slot
= (struct vec_descriptor
**) htab_find_slot (vec_desc_hash
, &loc
,
121 *slot
= XCNEW (struct vec_descriptor
);
122 (*slot
)->file
= name
;
123 (*slot
)->line
= line
;
124 (*slot
)->function
= function
;
125 (*slot
)->allocated
= 0;
130 /* Account the overhead. */
132 register_overhead (struct vec_prefix
*ptr
, size_t size
,
133 const char *name
, int line
, const char *function
)
135 struct vec_descriptor
*loc
= vec_descriptor (name
, line
, function
);
136 struct ptr_hash_entry
*p
= XNEW (struct ptr_hash_entry
);
143 ptr_hash
= htab_create (10, hash_ptr
, eq_ptr
, NULL
);
144 slot
= htab_find_slot_with_hash (ptr_hash
, ptr
, htab_hash_pointer (ptr
), INSERT
);
148 loc
->allocated
+= size
;
149 if (loc
->peak
< loc
->allocated
)
150 loc
->peak
+= loc
->allocated
;
154 /* Notice that the pointer has been freed. */
156 free_overhead (struct vec_prefix
*ptr
)
158 PTR
*slot
= htab_find_slot_with_hash (ptr_hash
, ptr
, htab_hash_pointer (ptr
),
160 struct ptr_hash_entry
*p
= (struct ptr_hash_entry
*) *slot
;
161 p
->loc
->allocated
-= p
->allocated
;
162 htab_clear_slot (ptr_hash
, slot
);
167 vec_heap_free (void *ptr
)
169 free_overhead ((struct vec_prefix
*)ptr
);
174 /* Calculate the new ALLOC value, making sure that RESERVE slots are
175 free. If EXACT grow exactly, otherwise grow exponentially. */
177 static inline unsigned
178 calculate_allocation (const struct vec_prefix
*pfx
, int reserve
, bool exact
)
183 gcc_assert (reserve
>= 0);
191 /* If there's no prefix, and we've not requested anything, then we
192 will create a NULL vector. */
195 /* We must have run out of room. */
196 gcc_assert (alloc
- num
< (unsigned) reserve
);
200 alloc
= num
+ reserve
;
203 /* Exponential growth. */
207 /* Double when small. */
210 /* Grow slower when large. */
211 alloc
= (alloc
* 3 / 2);
213 /* If this is still too small, set it to the right size. */
214 if (alloc
< num
+ reserve
)
215 alloc
= num
+ reserve
;
220 /* Ensure there are at least RESERVE free slots in VEC. If EXACT grow
221 exactly, else grow exponentially. As a special case, if VEC is
222 NULL and RESERVE is 0, no vector will be created. The vector's
223 trailing array is at VEC_OFFSET offset and consists of ELT_SIZE
227 vec_gc_o_reserve_1 (void *vec
, int reserve
, size_t vec_offset
, size_t elt_size
,
228 bool exact MEM_STAT_DECL
)
230 struct vec_prefix
*pfx
= (struct vec_prefix
*) vec
;
231 unsigned alloc
= calculate_allocation (pfx
, reserve
, exact
);
240 vec
= ggc_realloc_stat (vec
, vec_offset
+ alloc
* elt_size PASS_MEM_STAT
);
241 ((struct vec_prefix
*)vec
)->alloc
= alloc
;
243 ((struct vec_prefix
*)vec
)->num
= 0;
248 /* Ensure there are at least RESERVE free slots in VEC, growing
249 exponentially. If RESERVE < 0 grow exactly, else grow
250 exponentially. As a special case, if VEC is NULL, and RESERVE is
251 0, no vector will be created. */
254 vec_gc_p_reserve (void *vec
, int reserve MEM_STAT_DECL
)
256 return vec_gc_o_reserve_1 (vec
, reserve
,
257 offsetof (struct vec_prefix
, vec
),
258 sizeof (void *), false
262 /* Ensure there are at least RESERVE free slots in VEC, growing
263 exactly. If RESERVE < 0 grow exactly, else grow exponentially. As
264 a special case, if VEC is NULL, and RESERVE is 0, no vector will be
268 vec_gc_p_reserve_exact (void *vec
, int reserve MEM_STAT_DECL
)
270 return vec_gc_o_reserve_1 (vec
, reserve
,
271 offsetof (struct vec_prefix
, vec
),
272 sizeof (void *), true
276 /* As for vec_gc_p_reserve, but for object vectors. The vector's
277 trailing array is at VEC_OFFSET offset and consists of ELT_SIZE
281 vec_gc_o_reserve (void *vec
, int reserve
, size_t vec_offset
, size_t elt_size
284 return vec_gc_o_reserve_1 (vec
, reserve
, vec_offset
, elt_size
, false
288 /* As for vec_gc_p_reserve_exact, but for object vectors. The
289 vector's trailing array is at VEC_OFFSET offset and consists of
290 ELT_SIZE sized elements. */
293 vec_gc_o_reserve_exact (void *vec
, int reserve
, size_t vec_offset
,
294 size_t elt_size MEM_STAT_DECL
)
296 return vec_gc_o_reserve_1 (vec
, reserve
, vec_offset
, elt_size
, true
300 /* As for vec_gc_o_reserve_1, but for heap allocated vectors. */
303 vec_heap_o_reserve_1 (void *vec
, int reserve
, size_t vec_offset
,
304 size_t elt_size
, bool exact MEM_STAT_DECL
)
306 struct vec_prefix
*pfx
= (struct vec_prefix
*) vec
;
307 unsigned alloc
= calculate_allocation (pfx
, reserve
, exact
);
316 #ifdef GATHER_STATISTICS
321 vec
= xrealloc (vec
, vec_offset
+ alloc
* elt_size
);
322 ((struct vec_prefix
*)vec
)->alloc
= alloc
;
324 ((struct vec_prefix
*)vec
)->num
= 0;
325 #ifdef GATHER_STATISTICS
327 register_overhead ((struct vec_prefix
*)vec
,
328 vec_offset
+ alloc
* elt_size PASS_MEM_STAT
);
334 /* As for vec_gc_p_reserve, but for heap allocated vectors. */
337 vec_heap_p_reserve (void *vec
, int reserve MEM_STAT_DECL
)
339 return vec_heap_o_reserve_1 (vec
, reserve
,
340 offsetof (struct vec_prefix
, vec
),
341 sizeof (void *), false
345 /* As for vec_gc_p_reserve_exact, but for heap allocated vectors. */
348 vec_heap_p_reserve_exact (void *vec
, int reserve MEM_STAT_DECL
)
350 return vec_heap_o_reserve_1 (vec
, reserve
,
351 offsetof (struct vec_prefix
, vec
),
352 sizeof (void *), true
356 /* As for vec_gc_o_reserve, but for heap allocated vectors. */
359 vec_heap_o_reserve (void *vec
, int reserve
, size_t vec_offset
, size_t elt_size
362 return vec_heap_o_reserve_1 (vec
, reserve
, vec_offset
, elt_size
, false
366 /* As for vec_gc_o_reserve_exact, but for heap allocated vectors. */
369 vec_heap_o_reserve_exact (void *vec
, int reserve
, size_t vec_offset
,
370 size_t elt_size MEM_STAT_DECL
)
372 return vec_heap_o_reserve_1 (vec
, reserve
, vec_offset
, elt_size
, true
376 /* Stack vectors are a little different. VEC_alloc turns into a call
377 to vec_stack_p_reserve_exact1 and passes in space allocated via a
378 call to alloca. We record that pointer so that we know that we
379 shouldn't free it. If the vector is resized, we resize it on the
380 heap. We record the pointers in a vector and search it in LIFO
381 order--i.e., we look for the newest stack vectors first. We don't
382 expect too many stack vectors at any one level, and searching from
383 the end should normally be efficient even if they are used in a
384 recursive function. */
386 typedef void *void_p
;
388 DEF_VEC_ALLOC_P(void_p
,heap
);
390 static VEC(void_p
,heap
) *stack_vecs
;
392 /* Allocate a vector which uses alloca for the initial allocation.
393 SPACE is space allocated using alloca, ALLOC is the number of
394 entries allocated. */
397 vec_stack_p_reserve_exact_1 (int alloc
, void *space
)
399 struct vec_prefix
*pfx
= (struct vec_prefix
*) space
;
401 VEC_safe_push (void_p
, heap
, stack_vecs
, space
);
409 /* Grow a vector allocated using alloca. When this happens, we switch
410 back to heap allocation. We remove the vector from stack_vecs, if
411 it is there, since we no longer need to avoid freeing it. */
414 vec_stack_o_reserve_1 (void *vec
, int reserve
, size_t vec_offset
,
415 size_t elt_size
, bool exact MEM_STAT_DECL
)
422 for (ix
= VEC_length (void_p
, stack_vecs
); ix
> 0; --ix
)
424 if (VEC_index (void_p
, stack_vecs
, ix
- 1) == vec
)
426 VEC_unordered_remove (void_p
, stack_vecs
, ix
- 1);
434 /* VEC is already on the heap. */
435 return vec_heap_o_reserve_1 (vec
, reserve
, vec_offset
, elt_size
,
436 exact PASS_MEM_STAT
);
439 /* Move VEC to the heap. */
440 reserve
+= ((struct vec_prefix
*) vec
)->num
;
441 newvec
= vec_heap_o_reserve_1 (NULL
, reserve
, vec_offset
, elt_size
,
442 exact PASS_MEM_STAT
);
445 ((struct vec_prefix
*) newvec
)->num
= ((struct vec_prefix
*) vec
)->num
;
446 memcpy (((struct vec_prefix
*) newvec
)->vec
,
447 ((struct vec_prefix
*) vec
)->vec
,
448 ((struct vec_prefix
*) vec
)->num
* elt_size
);
453 /* Grow a vector allocated on the stack. */
456 vec_stack_p_reserve (void *vec
, int reserve MEM_STAT_DECL
)
458 return vec_stack_o_reserve_1 (vec
, reserve
,
459 offsetof (struct vec_prefix
, vec
),
460 sizeof (void *), false
464 /* Exact version of vec_stack_p_reserve. */
467 vec_stack_p_reserve_exact (void *vec
, int reserve MEM_STAT_DECL
)
469 return vec_stack_o_reserve_1 (vec
, reserve
,
470 offsetof (struct vec_prefix
, vec
),
471 sizeof (void *), true
475 /* Like vec_stack_p_reserve, but for objects. */
478 vec_stack_o_reserve (void *vec
, int reserve
, size_t vec_offset
,
479 size_t elt_size MEM_STAT_DECL
)
481 return vec_stack_o_reserve_1 (vec
, reserve
, vec_offset
, elt_size
, false
485 /* Like vec_stack_p_reserve_exact, but for objects. */
488 vec_stack_o_reserve_exact (void *vec
, int reserve
, size_t vec_offset
,
489 size_t elt_size MEM_STAT_DECL
)
491 return vec_stack_o_reserve_1 (vec
, reserve
, vec_offset
, elt_size
, true
495 /* Free a vector allocated on the stack. Don't actually free it if we
496 find it in the hash table. */
499 vec_stack_free (void *vec
)
503 for (ix
= VEC_length (void_p
, stack_vecs
); ix
> 0; --ix
)
505 if (VEC_index (void_p
, stack_vecs
, ix
- 1) == vec
)
507 VEC_unordered_remove (void_p
, stack_vecs
, ix
- 1);
512 /* VEC was not on the list of vecs allocated on the stack, so it
513 must be allocated on the heap. */
518 /* Issue a vector domain error, and then fall over. */
521 vec_assert_fail (const char *op
, const char *struct_name
,
522 const char *file
, unsigned int line
, const char *function
)
524 internal_error ("vector %s %s domain error, in %s at %s:%u",
525 struct_name
, op
, function
, trim_filename (file
), line
);
529 #ifdef GATHER_STATISTICS
530 /* Helper for qsort; sort descriptors by amount of memory consumed. */
532 cmp_statistic (const void *loc1
, const void *loc2
)
534 const struct vec_descriptor
*const l1
=
535 *(const struct vec_descriptor
*const *) loc1
;
536 const struct vec_descriptor
*const l2
=
537 *(const struct vec_descriptor
*const *) loc2
;
539 diff
= l1
->allocated
- l2
->allocated
;
541 diff
= l1
->peak
- l2
->peak
;
543 diff
= l1
->times
- l2
->times
;
544 return diff
> 0 ? 1 : diff
< 0 ? -1 : 0;
546 /* Collect array of the descriptors from hashtable. */
547 static struct vec_descriptor
**loc_array
;
549 add_statistics (void **slot
, void *b
)
552 loc_array
[*n
] = (struct vec_descriptor
*) *slot
;
557 /* Dump per-site memory statistics. */
560 dump_vec_loc_statistics (void)
562 #ifdef GATHER_STATISTICS
565 size_t allocated
= 0;
569 loc_array
= XCNEWVEC (struct vec_descriptor
*, vec_desc_hash
->n_elements
);
570 fprintf (stderr
, "Heap vectors:\n");
571 fprintf (stderr
, "\n%-48s %10s %10s %10s\n",
572 "source location", "Leak", "Peak", "Times");
573 fprintf (stderr
, "-------------------------------------------------------\n");
574 htab_traverse (vec_desc_hash
, add_statistics
, &nentries
);
575 qsort (loc_array
, nentries
, sizeof (*loc_array
), cmp_statistic
);
576 for (i
= 0; i
< nentries
; i
++)
578 struct vec_descriptor
*d
= loc_array
[i
];
579 allocated
+= d
->allocated
;
582 for (i
= 0; i
< nentries
; i
++)
584 struct vec_descriptor
*d
= loc_array
[i
];
585 const char *s1
= d
->file
;
587 while ((s2
= strstr (s1
, "gcc/")))
589 sprintf (s
, "%s:%i (%s)", s1
, d
->line
, d
->function
);
591 fprintf (stderr
, "%-48s %10li:%4.1f%% %10li %10li:%4.1f%% \n", s
,
593 (d
->allocated
) * 100.0 / allocated
,
596 (d
->times
) * 100.0 / times
);
598 fprintf (stderr
, "%-48s %10ld %10ld\n",
599 "Total", (long)allocated
, (long)times
);
600 fprintf (stderr
, "\n%-48s %10s %10s %10s\n",
601 "source location", "Leak", "Peak", "Times");
602 fprintf (stderr
, "-------------------------------------------------------\n");