]> gcc.gnu.org Git - gcc.git/blame - gcc/vec.c
Remove trailing white spaces.
[gcc.git] / gcc / vec.c
CommitLineData
ada55151 1/* Vector API for GNU compiler.
66647d44 2 Copyright (C) 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
ada55151
NS
3 Contributed by Nathan Sidwell <nathan@codesourcery.com>
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9dcd6f09 9Software Foundation; either version 3, or (at your option) any later
ada55151
NS
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
9dcd6f09
NC
18along with GCC; see the file COPYING3. If not see
19<http://www.gnu.org/licenses/>. */
ada55151 20
2d5bc016
DD
21/* This file is compiled twice: once for the generator programs
22 once for the compiler. */
23#ifdef GENERATOR_FILE
24#include "bconfig.h"
25#else
ada55151 26#include "config.h"
2d5bc016
DD
27#endif
28
ada55151
NS
29#include "system.h"
30#include "ggc.h"
31#include "vec.h"
ada55151 32#include "coretypes.h"
4c714dd4 33#include "toplev.h"
d3492572 34#include "hashtab.h"
ada55151 35
b8698a0f 36struct vec_prefix
ada55151 37{
3cbf09de
NS
38 unsigned num;
39 unsigned alloc;
ada55151
NS
40 void *vec[1];
41};
42
d3492572
JH
43
44#ifdef GATHER_STATISTICS
45
46/* Store information about each particular vector. */
47struct vec_descriptor
48{
49 const char *function;
50 const char *file;
51 int line;
52 size_t allocated;
53 size_t times;
54 size_t peak;
55};
56
57
58/* Hashtable mapping vec addresses to descriptors. */
59static htab_t vec_desc_hash;
60
61/* Hashtable helpers. */
62static hashval_t
63hash_descriptor (const void *p)
64{
65 const struct vec_descriptor *const d =
66 (const struct vec_descriptor *) p;
67 return htab_hash_pointer (d->file) + d->line;
68}
69static int
70eq_descriptor (const void *p1, const void *p2)
71{
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;
75}
76
77/* Hashtable converting address of allocated field to loc descriptor. */
78static htab_t ptr_hash;
79struct ptr_hash_entry
80{
81 void *ptr;
82 struct vec_descriptor *loc;
83 size_t allocated;
84};
85
86/* Hash table helpers functions. */
87static hashval_t
88hash_ptr (const void *p)
89{
90 const struct ptr_hash_entry *const d = (const struct ptr_hash_entry *) p;
91
92 return htab_hash_pointer (d->ptr);
93}
94
95static int
96eq_ptr (const void *p1, const void *p2)
97{
98 const struct ptr_hash_entry *const p = (const struct ptr_hash_entry *) p1;
99
100 return (p->ptr == p2);
101}
102
103/* Return descriptor for given call site, create new one if needed. */
104static struct vec_descriptor *
105vec_descriptor (const char *name, int line, const char *function)
106{
107 struct vec_descriptor loc;
108 struct vec_descriptor **slot;
109
110 loc.file = name;
111 loc.line = line;
112 loc.function = function;
113 if (!vec_desc_hash)
114 vec_desc_hash = htab_create (10, hash_descriptor, eq_descriptor, NULL);
115
f136c8ae
RAE
116 slot = (struct vec_descriptor **) htab_find_slot (vec_desc_hash, &loc,
117 INSERT);
d3492572
JH
118 if (*slot)
119 return *slot;
120 *slot = XCNEW (struct vec_descriptor);
121 (*slot)->file = name;
122 (*slot)->line = line;
123 (*slot)->function = function;
124 (*slot)->allocated = 0;
125 (*slot)->peak = 0;
126 return *slot;
127}
128
129/* Account the overhead. */
130static void
131register_overhead (struct vec_prefix *ptr, size_t size,
132 const char *name, int line, const char *function)
133{
134 struct vec_descriptor *loc = vec_descriptor (name, line, function);
135 struct ptr_hash_entry *p = XNEW (struct ptr_hash_entry);
136 PTR *slot;
137
138 p->ptr = ptr;
139 p->loc = loc;
140 p->allocated = size;
141 if (!ptr_hash)
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);
144 gcc_assert (!*slot);
145 *slot = p;
146
147 loc->allocated += size;
148 if (loc->peak < loc->allocated)
149 loc->peak += loc->allocated;
150 loc->times++;
151}
152
153/* Notice that the pointer has been freed. */
154static void
155free_overhead (struct vec_prefix *ptr)
156{
157 PTR *slot = htab_find_slot_with_hash (ptr_hash, ptr, htab_hash_pointer (ptr),
158 NO_INSERT);
159 struct ptr_hash_entry *p = (struct ptr_hash_entry *) *slot;
160 p->loc->allocated -= p->allocated;
161 htab_clear_slot (ptr_hash, slot);
162 free (p);
163}
164
165void
166vec_heap_free (void *ptr)
167{
168 free_overhead ((struct vec_prefix *)ptr);
169 free (ptr);
170}
171#endif
172
efb7e1e0
ILT
173/* Calculate the new ALLOC value, making sure that RESERVE slots are
174 free. If EXACT grow exactly, otherwise grow exponentially. */
d4e6fecb
NS
175
176static inline unsigned
efb7e1e0 177calculate_allocation (const struct vec_prefix *pfx, int reserve, bool exact)
d4e6fecb
NS
178{
179 unsigned alloc = 0;
180 unsigned num = 0;
181
efb7e1e0
ILT
182 gcc_assert (reserve >= 0);
183
d4e6fecb
NS
184 if (pfx)
185 {
186 alloc = pfx->alloc;
187 num = pfx->num;
188 }
189 else if (!reserve)
190 /* If there's no prefix, and we've not requested anything, then we
191 will create a NULL vector. */
192 return 0;
b8698a0f 193
d4e6fecb 194 /* We must have run out of room. */
efb7e1e0 195 gcc_assert (alloc - num < (unsigned) reserve);
b8698a0f 196
efb7e1e0 197 if (exact)
d4e6fecb 198 /* Exact size. */
efb7e1e0 199 alloc = num + reserve;
d4e6fecb
NS
200 else
201 {
202 /* Exponential growth. */
203 if (!alloc)
204 alloc = 4;
205 else if (alloc < 16)
206 /* Double when small. */
207 alloc = alloc * 2;
208 else
209 /* Grow slower when large. */
210 alloc = (alloc * 3 / 2);
b8698a0f 211
d4e6fecb
NS
212 /* If this is still too small, set it to the right size. */
213 if (alloc < num + reserve)
214 alloc = num + reserve;
215 }
216 return alloc;
217}
218
efb7e1e0
ILT
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
223 sized elements. */
ada55151 224
efb7e1e0
ILT
225static void *
226vec_gc_o_reserve_1 (void *vec, int reserve, size_t vec_offset, size_t elt_size,
227 bool exact MEM_STAT_DECL)
ada55151 228{
3d9a9f94 229 struct vec_prefix *pfx = (struct vec_prefix *) vec;
415a06c2 230 unsigned alloc = calculate_allocation (pfx, reserve, exact);
b8698a0f 231
d4e6fecb 232 if (!alloc)
d3492572
JH
233 {
234 if (pfx)
235 ggc_free (pfx);
236 return NULL;
237 }
b8698a0f 238
7de5bccc
NS
239 vec = ggc_realloc_stat (vec, vec_offset + alloc * elt_size PASS_MEM_STAT);
240 ((struct vec_prefix *)vec)->alloc = alloc;
241 if (!pfx)
242 ((struct vec_prefix *)vec)->num = 0;
b8698a0f 243
ada55151
NS
244 return vec;
245}
246
efb7e1e0
ILT
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. */
4c254e68
NS
251
252void *
efb7e1e0 253vec_gc_p_reserve (void *vec, int reserve MEM_STAT_DECL)
4c254e68 254{
efb7e1e0
ILT
255 return vec_gc_o_reserve_1 (vec, reserve,
256 offsetof (struct vec_prefix, vec),
257 sizeof (void *), false
4c254e68
NS
258 PASS_MEM_STAT);
259}
260
efb7e1e0
ILT
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
264 created. */
4c254e68
NS
265
266void *
efb7e1e0
ILT
267vec_gc_p_reserve_exact (void *vec, int reserve MEM_STAT_DECL)
268{
269 return vec_gc_o_reserve_1 (vec, reserve,
270 offsetof (struct vec_prefix, vec),
271 sizeof (void *), true
272 PASS_MEM_STAT);
273}
274
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
277 sized elements. */
278
279void *
280vec_gc_o_reserve (void *vec, int reserve, size_t vec_offset, size_t elt_size
281 MEM_STAT_DECL)
282{
283 return vec_gc_o_reserve_1 (vec, reserve, vec_offset, elt_size, false
284 PASS_MEM_STAT);
285}
286
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. */
290
291void *
292vec_gc_o_reserve_exact (void *vec, int reserve, size_t vec_offset,
293 size_t elt_size MEM_STAT_DECL)
294{
295 return vec_gc_o_reserve_1 (vec, reserve, vec_offset, elt_size, true
296 PASS_MEM_STAT);
297}
298
299/* As for vec_gc_o_reserve_1, but for heap allocated vectors. */
300
301static void *
302vec_heap_o_reserve_1 (void *vec, int reserve, size_t vec_offset,
303 size_t elt_size, bool exact MEM_STAT_DECL)
4c254e68 304{
3d9a9f94 305 struct vec_prefix *pfx = (struct vec_prefix *) vec;
efb7e1e0 306 unsigned alloc = calculate_allocation (pfx, reserve, exact);
4c254e68 307
d4e6fecb 308 if (!alloc)
d3492572
JH
309 {
310 if (pfx)
311 vec_heap_free (pfx);
312 return NULL;
313 }
314
315#ifdef GATHER_STATISTICS
316 if (vec)
317 free_overhead (pfx);
318#endif
b8698a0f 319
4c254e68
NS
320 vec = xrealloc (vec, vec_offset + alloc * elt_size);
321 ((struct vec_prefix *)vec)->alloc = alloc;
322 if (!pfx)
323 ((struct vec_prefix *)vec)->num = 0;
d3492572
JH
324#ifdef GATHER_STATISTICS
325 if (vec)
326 register_overhead ((struct vec_prefix *)vec,
327 vec_offset + alloc * elt_size PASS_MEM_STAT);
328#endif
b8698a0f 329
4c254e68
NS
330 return vec;
331}
332
efb7e1e0
ILT
333/* As for vec_gc_p_reserve, but for heap allocated vectors. */
334
335void *
336vec_heap_p_reserve (void *vec, int reserve MEM_STAT_DECL)
337{
338 return vec_heap_o_reserve_1 (vec, reserve,
339 offsetof (struct vec_prefix, vec),
340 sizeof (void *), false
341 PASS_MEM_STAT);
342}
343
344/* As for vec_gc_p_reserve_exact, but for heap allocated vectors. */
345
346void *
347vec_heap_p_reserve_exact (void *vec, int reserve MEM_STAT_DECL)
348{
349 return vec_heap_o_reserve_1 (vec, reserve,
350 offsetof (struct vec_prefix, vec),
351 sizeof (void *), true
352 PASS_MEM_STAT);
353}
354
355/* As for vec_gc_o_reserve, but for heap allocated vectors. */
356
357void *
358vec_heap_o_reserve (void *vec, int reserve, size_t vec_offset, size_t elt_size
359 MEM_STAT_DECL)
360{
361 return vec_heap_o_reserve_1 (vec, reserve, vec_offset, elt_size, false
362 PASS_MEM_STAT);
363}
364
365/* As for vec_gc_o_reserve_exact, but for heap allocated vectors. */
366
367void *
368vec_heap_o_reserve_exact (void *vec, int reserve, size_t vec_offset,
369 size_t elt_size MEM_STAT_DECL)
370{
371 return vec_heap_o_reserve_1 (vec, reserve, vec_offset, elt_size, true
372 PASS_MEM_STAT);
373}
374
c2569604
ILT
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. */
384
385typedef void *void_p;
386DEF_VEC_P(void_p);
387DEF_VEC_ALLOC_P(void_p,heap);
388
389static VEC(void_p,heap) *stack_vecs;
390
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. */
394
395void *
396vec_stack_p_reserve_exact_1 (int alloc, void *space)
397{
398 struct vec_prefix *pfx = (struct vec_prefix *) space;
399
400 VEC_safe_push (void_p, heap, stack_vecs, space);
401
402 pfx->num = 0;
403 pfx->alloc = alloc;
404
405 return space;
406}
407
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. */
411
412static void *
413vec_stack_o_reserve_1 (void *vec, int reserve, size_t vec_offset,
414 size_t elt_size, bool exact MEM_STAT_DECL)
415{
416 bool found;
417 unsigned int ix;
418 void *newvec;
419
420 found = false;
421 for (ix = VEC_length (void_p, stack_vecs); ix > 0; --ix)
422 {
423 if (VEC_index (void_p, stack_vecs, ix - 1) == vec)
424 {
425 VEC_unordered_remove (void_p, stack_vecs, ix - 1);
426 found = true;
427 break;
428 }
429 }
430
431 if (!found)
432 {
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);
436 }
437
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);
442 if (newvec && vec)
443 {
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);
448 }
449 return newvec;
450}
451
452/* Grow a vector allocated on the stack. */
453
454void *
455vec_stack_p_reserve (void *vec, int reserve MEM_STAT_DECL)
456{
457 return vec_stack_o_reserve_1 (vec, reserve,
458 offsetof (struct vec_prefix, vec),
459 sizeof (void *), false
460 PASS_MEM_STAT);
461}
462
463/* Exact version of vec_stack_p_reserve. */
464
465void *
466vec_stack_p_reserve_exact (void *vec, int reserve MEM_STAT_DECL)
467{
468 return vec_stack_o_reserve_1 (vec, reserve,
469 offsetof (struct vec_prefix, vec),
470 sizeof (void *), true
471 PASS_MEM_STAT);
472}
473
474/* Like vec_stack_p_reserve, but for objects. */
475
476void *
477vec_stack_o_reserve (void *vec, int reserve, size_t vec_offset,
478 size_t elt_size MEM_STAT_DECL)
479{
480 return vec_stack_o_reserve_1 (vec, reserve, vec_offset, elt_size, false
481 PASS_MEM_STAT);
482}
483
484/* Like vec_stack_p_reserve_exact, but for objects. */
485
486void *
487vec_stack_o_reserve_exact (void *vec, int reserve, size_t vec_offset,
488 size_t elt_size MEM_STAT_DECL)
489{
490 return vec_stack_o_reserve_1 (vec, reserve, vec_offset, elt_size, true
491 PASS_MEM_STAT);
492}
493
494/* Free a vector allocated on the stack. Don't actually free it if we
495 find it in the hash table. */
496
497void
498vec_stack_free (void *vec)
499{
500 unsigned int ix;
501
502 for (ix = VEC_length (void_p, stack_vecs); ix > 0; --ix)
503 {
504 if (VEC_index (void_p, stack_vecs, ix - 1) == vec)
505 {
506 VEC_unordered_remove (void_p, stack_vecs, ix - 1);
507 return;
508 }
509 }
510
511 /* VEC was not on the list of vecs allocated on the stack, so it
512 must be allocated on the heap. */
513 vec_heap_free (vec);
514}
515
ada55151
NS
516#if ENABLE_CHECKING
517/* Issue a vector domain error, and then fall over. */
518
519void
520vec_assert_fail (const char *op, const char *struct_name,
dae1dd2e 521 const char *file, unsigned int line, const char *function)
ada55151
NS
522{
523 internal_error ("vector %s %s domain error, in %s at %s:%u",
70ce47b5 524 struct_name, op, function, trim_filename (file), line);
ada55151
NS
525}
526#endif
d3492572
JH
527
528#ifdef GATHER_STATISTICS
529/* Helper for qsort; sort descriptors by amount of memory consumed. */
530static int
531cmp_statistic (const void *loc1, const void *loc2)
532{
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;
537 long diff;
538 diff = l1->allocated - l2->allocated;
539 if (!diff)
540 diff = l1->peak - l2->peak;
541 if (!diff)
542 diff = l1->times - l2->times;
543 return diff > 0 ? 1 : diff < 0 ? -1 : 0;
544}
545/* Collect array of the descriptors from hashtable. */
546static struct vec_descriptor **loc_array;
547static int
548add_statistics (void **slot, void *b)
549{
550 int *n = (int *)b;
551 loc_array[*n] = (struct vec_descriptor *) *slot;
552 (*n)++;
553 return 1;
554}
555
556/* Dump per-site memory statistics. */
557#endif
558void
559dump_vec_loc_statistics (void)
560{
561#ifdef GATHER_STATISTICS
562 int nentries = 0;
563 char s[4096];
564 size_t allocated = 0;
565 size_t times = 0;
566 int i;
567
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++)
576 {
577 struct vec_descriptor *d = loc_array[i];
578 allocated += d->allocated;
579 times += d->times;
580 }
581 for (i = 0; i < nentries; i++)
582 {
583 struct vec_descriptor *d = loc_array[i];
584 const char *s1 = d->file;
585 const char *s2;
586 while ((s2 = strstr (s1, "gcc/")))
587 s1 = s2 + 4;
588 sprintf (s, "%s:%i (%s)", s1, d->line, d->function);
589 s[48] = 0;
590 fprintf (stderr, "%-48s %10li:%4.1f%% %10li %10li:%4.1f%% \n", s,
591 (long)d->allocated,
592 (d->allocated) * 100.0 / allocated,
593 (long)d->peak,
594 (long)d->times,
595 (d->times) * 100.0 / times);
596 }
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");
602#endif
603}
This page took 2.487351 seconds and 5 git commands to generate.