]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/vec.h
New memory allocation statistics infrastructure.
[thirdparty/gcc.git] / gcc / vec.h
CommitLineData
190183c5 1/* Vector API for GNU compiler.
d353bf18 2 Copyright (C) 2004-2015 Free Software Foundation, Inc.
190183c5 3 Contributed by Nathan Sidwell <nathan@codesourcery.com>
2b15d2ba 4 Re-implemented in C++ by Diego Novillo <dnovillo@google.com>
190183c5 5
6This file is part of GCC.
7
8GCC is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
8c4c00c1 10Software Foundation; either version 3, or (at your option) any later
190183c5 11version.
12
13GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License
8c4c00c1 19along with GCC; see the file COPYING3. If not see
20<http://www.gnu.org/licenses/>. */
190183c5 21
22#ifndef GCC_VEC_H
23#define GCC_VEC_H
24
f1f41a6c 25/* FIXME - When compiling some of the gen* binaries, we cannot enable GC
26 support because the headers generated by gengtype are still not
27 present. In particular, the header file gtype-desc.h is missing,
28 so compilation may fail if we try to include ggc.h.
29
30 Since we use some of those declarations, we need to provide them
31 (even if the GC-based templates are not used). This is not a
32 problem because the code that runs before gengtype is built will
33 never need to use GC vectors. But it does force us to declare
34 these functions more than once. */
35#ifdef GENERATOR_FILE
36#define VEC_GC_ENABLED 0
37#else
38#define VEC_GC_ENABLED 1
39#endif // GENERATOR_FILE
40
41#include "statistics.h" // For CXX_MEM_STAT_INFO.
42
43#if VEC_GC_ENABLED
44#include "ggc.h"
45#else
46# ifndef GCC_GGC_H
47 /* Even if we think that GC is not enabled, the test that sets it is
48 weak. There are files compiled with -DGENERATOR_FILE that already
49 include ggc.h. We only need to provide these definitions if ggc.h
50 has not been included. Sigh. */
881f903e 51
f1f41a6c 52 extern void ggc_free (void *);
53 extern size_t ggc_round_alloc_size (size_t requested_size);
0ff42de5 54 extern void *ggc_realloc (void *, size_t MEM_STAT_DECL);
f1f41a6c 55# endif // GCC_GGC_H
56#endif // VEC_GC_ENABLED
ea269688 57
de2b4872 58/* Templated vector type and associated interfaces.
59
60 The interface functions are typesafe and use inline functions,
61 sometimes backed by out-of-line generic functions. The vectors are
62 designed to interoperate with the GTY machinery.
63
de2b4872 64 There are both 'index' and 'iterate' accessors. The index accessor
65 is implemented by operator[]. The iterator returns a boolean
66 iteration condition and updates the iteration variable passed by
67 reference. Because the iterator will be inlined, the address-of
68 can be optimized away.
930bdacf 69
190183c5 70 Each operation that increases the number of active elements is
71 available in 'quick' and 'safe' variants. The former presumes that
72 there is sufficient allocated space for the operation to succeed
1fa3a8f6 73 (it dies if there is not). The latter will reallocate the
190183c5 74 vector, if needed. Reallocation causes an exponential increase in
75 vector size. If you know you will be adding N elements, it would
76 be more efficient to use the reserve operation before adding the
046bfc77 77 elements with the 'quick' operation. This will ensure there are at
78 least as many elements as you ask for, it will exponentially
79 increase if there are too few spare slots. If you want reserve a
80 specific number of slots, but do not want the exponential increase
24ffec38 81 (for instance, you know this is the last allocation), use the
82 reserve_exact operation. You can also create a vector of a
046bfc77 83 specific size from the get go.
190183c5 84
85 You should prefer the push and pop operations, as they append and
15f5ee9f 86 remove from the end of the vector. If you need to remove several
87 items in one go, use the truncate operation. The insert and remove
190183c5 88 operations allow you to change elements in the middle of the
89 vector. There are two remove operations, one which preserves the
90 element ordering 'ordered_remove', and one which does not
91 'unordered_remove'. The latter function copies the end element
046bfc77 92 into the removed slot, rather than invoke a memmove operation. The
93 'lower_bound' function will determine where to place an item in the
145fce5e 94 array using insert that will maintain sorted order.
930bdacf 95
f1f41a6c 96 Vectors are template types with three arguments: the type of the
97 elements in the vector, the allocation strategy, and the physical
98 layout to use
99
100 Four allocation strategies are supported:
101
102 - Heap: allocation is done using malloc/free. This is the
103 default allocation strategy.
104
f1f41a6c 105 - GC: allocation is done using ggc_alloc/ggc_free.
106
107 - GC atomic: same as GC with the exception that the elements
108 themselves are assumed to be of an atomic type that does
109 not need to be garbage collected. This means that marking
110 routines do not need to traverse the array marking the
111 individual elements. This increases the performance of
112 GC activities.
113
114 Two physical layouts are supported:
115
116 - Embedded: The vector is structured using the trailing array
117 idiom. The last member of the structure is an array of size
118 1. When the vector is initially allocated, a single memory
119 block is created to hold the vector's control data and the
120 array of elements. These vectors cannot grow without
121 reallocation (see discussion on embeddable vectors below).
122
123 - Space efficient: The vector is structured as a pointer to an
124 embedded vector. This is the default layout. It means that
125 vectors occupy a single word of storage before initial
126 allocation. Vectors are allowed to grow (the internal
127 pointer is reallocated but the main vector instance does not
128 need to relocate).
129
130 The type, allocation and layout are specified when the vector is
131 declared.
48e1416a 132
930bdacf 133 If you need to directly manipulate a vector, then the 'address'
134 accessor will return the address of the start of the vector. Also
135 the 'space' predicate will tell you whether there is spare capacity
136 in the vector. You will not normally need to use these two functions.
48e1416a 137
f1f41a6c 138 Notes on the different layout strategies
139
140 * Embeddable vectors (vec<T, A, vl_embed>)
141
142 These vectors are suitable to be embedded in other data
143 structures so that they can be pre-allocated in a contiguous
144 memory block.
145
146 Embeddable vectors are implemented using the trailing array
147 idiom, thus they are not resizeable without changing the address
148 of the vector object itself. This means you cannot have
149 variables or fields of embeddable vector type -- always use a
150 pointer to a vector. The one exception is the final field of a
151 structure, which could be a vector type.
152
153 You will have to use the embedded_size & embedded_init calls to
154 create such objects, and they will not be resizeable (so the
155 'safe' allocation variants are not available).
156
157 Properties of embeddable vectors:
158
159 - The whole vector and control data are allocated in a single
160 contiguous block. It uses the trailing-vector idiom, so
161 allocation must reserve enough space for all the elements
162 in the vector plus its control data.
163 - The vector cannot be re-allocated.
164 - The vector cannot grow nor shrink.
165 - No indirections needed for access/manipulation.
166 - It requires 2 words of storage (prior to vector allocation).
167
168
169 * Space efficient vector (vec<T, A, vl_ptr>)
170
171 These vectors can grow dynamically and are allocated together
172 with their control data. They are suited to be included in data
173 structures. Prior to initial allocation, they only take a single
174 word of storage.
175
176 These vectors are implemented as a pointer to embeddable vectors.
177 The semantics allow for this pointer to be NULL to represent
178 empty vectors. This way, empty vectors occupy minimal space in
179 the structure containing them.
180
181 Properties:
182
183 - The whole vector and control data are allocated in a single
184 contiguous block.
185 - The whole vector may be re-allocated.
186 - Vector data may grow and shrink.
187 - Access and manipulation requires a pointer test and
188 indirection.
189 - It requires 1 word of storage (prior to vector allocation).
190183c5 190
191 An example of their use would be,
192
190183c5 193 struct my_struct {
f1f41a6c 194 // A space-efficient vector of tree pointers in GC memory.
195 vec<tree, va_gc, vl_ptr> v;
190183c5 196 };
197
198 struct my_struct *s;
199
f1f41a6c 200 if (s->v.length ()) { we have some contents }
201 s->v.safe_push (decl); // append some decl onto the end
202 for (ix = 0; s->v.iterate (ix, &elt); ix++)
6c798041 203 { do something with elt }
190183c5 204*/
205
f1f41a6c 206/* Support function for statistics. */
207extern void dump_vec_loc_statistics (void);
2b15d2ba 208
0ff42de5 209/* Hashtable mapping vec addresses to descriptors. */
210extern htab_t vec_mem_usage_hash;
2b15d2ba 211
f1f41a6c 212/* Control data for vectors. This contains the number of allocated
213 and used slots inside a vector. */
2b15d2ba 214
cac0c158 215struct vec_prefix
2b15d2ba 216{
aad734b2 217 /* FIXME - These fields should be private, but we need to cater to
218 compilers that have stricter notions of PODness for types. */
cac0c158 219
f1f41a6c 220 /* Memory allocation support routines in vec.c. */
0ff42de5 221 void register_overhead (void *, size_t, size_t CXX_MEM_STAT_INFO);
222 void release_overhead (void *, size_t, bool CXX_MEM_STAT_INFO);
cac0c158 223 static unsigned calculate_allocation (vec_prefix *, unsigned, bool);
ec456ba8 224 static unsigned calculate_allocation_1 (unsigned, unsigned);
f1f41a6c 225
226 /* Note that vec_prefix should be a base class for vec, but we use
227 offsetof() on vector fields of tree structures (e.g.,
228 tree_binfo::base_binfos), and offsetof only supports base types.
229
230 To compensate, we make vec_prefix a field inside vec and make
231 vec a friend class of vec_prefix so it can access its fields. */
29c697ae 232 template <typename, typename, typename> friend struct vec;
f1f41a6c 233
234 /* The allocator types also need access to our internals. */
235 friend struct va_gc;
236 friend struct va_gc_atomic;
237 friend struct va_heap;
f1f41a6c 238
d70aebca 239 unsigned m_alloc : 31;
ec456ba8 240 unsigned m_using_auto_storage : 1;
fd3aba29 241 unsigned m_num;
2b15d2ba 242};
243
ec456ba8 244/* Calculate the number of slots to reserve a vector, making sure that
245 RESERVE slots are free. If EXACT grow exactly, otherwise grow
246 exponentially. PFX is the control data for the vector. */
247
248inline unsigned
249vec_prefix::calculate_allocation (vec_prefix *pfx, unsigned reserve,
250 bool exact)
251{
252 if (exact)
253 return (pfx ? pfx->m_num : 0) + reserve;
254 else if (!pfx)
255 return MAX (4, reserve);
256 return calculate_allocation_1 (pfx->m_alloc, pfx->m_num + reserve);
257}
258
29c697ae 259template<typename, typename, typename> struct vec;
de2b4872 260
f1f41a6c 261/* Valid vector layouts
de2b4872 262
f1f41a6c 263 vl_embed - Embeddable vector that uses the trailing array idiom.
264 vl_ptr - Space efficient vector that uses a pointer to an
265 embeddable vector. */
266struct vl_embed { };
267struct vl_ptr { };
de2b4872 268
de2b4872 269
f1f41a6c 270/* Types of supported allocations
de2b4872 271
f1f41a6c 272 va_heap - Allocation uses malloc/free.
273 va_gc - Allocation uses ggc_alloc.
274 va_gc_atomic - Same as GC, but individual elements of the array
d70aebca 275 do not need to be marked during collection. */
de2b4872 276
f1f41a6c 277/* Allocator type for heap vectors. */
278struct va_heap
279{
280 /* Heap vectors are frequently regular instances, so use the vl_ptr
281 layout for them. */
282 typedef vl_ptr default_layout;
de2b4872 283
f1f41a6c 284 template<typename T>
285 static void reserve (vec<T, va_heap, vl_embed> *&, unsigned, bool
286 CXX_MEM_STAT_INFO);
de2b4872 287
f1f41a6c 288 template<typename T>
289 static void release (vec<T, va_heap, vl_embed> *&);
290};
de2b4872 291
de2b4872 292
f1f41a6c 293/* Allocator for heap memory. Ensure there are at least RESERVE free
294 slots in V. If EXACT is true, grow exactly, else grow
295 exponentially. As a special case, if the vector had not been
296 allocated and and RESERVE is 0, no vector will be created. */
de2b4872 297
f1f41a6c 298template<typename T>
299inline void
300va_heap::reserve (vec<T, va_heap, vl_embed> *&v, unsigned reserve, bool exact
301 MEM_STAT_DECL)
302{
cac0c158 303 unsigned alloc
fd3aba29 304 = vec_prefix::calculate_allocation (v ? &v->m_vecpfx : 0, reserve, exact);
ec456ba8 305 gcc_checking_assert (alloc);
de2b4872 306
f1f41a6c 307 if (GATHER_STATISTICS && v)
0ff42de5 308 v->m_vecpfx.release_overhead (v, v->allocated (), false);
de2b4872 309
f1f41a6c 310 size_t size = vec<T, va_heap, vl_embed>::embedded_size (alloc);
311 unsigned nelem = v ? v->length () : 0;
312 v = static_cast <vec<T, va_heap, vl_embed> *> (xrealloc (v, size));
313 v->embedded_init (alloc, nelem);
de2b4872 314
f1f41a6c 315 if (GATHER_STATISTICS)
0ff42de5 316 v->m_vecpfx.register_overhead (v, alloc, nelem PASS_MEM_STAT);
f1f41a6c 317}
2b15d2ba 318
de2b4872 319
f1f41a6c 320/* Free the heap space allocated for vector V. */
2b15d2ba 321
322template<typename T>
323void
f1f41a6c 324va_heap::release (vec<T, va_heap, vl_embed> *&v)
2b15d2ba 325{
aad734b2 326 if (v == NULL)
327 return;
328
f1f41a6c 329 if (GATHER_STATISTICS)
0ff42de5 330 v->m_vecpfx.release_overhead (v, v->allocated (), true);
f1f41a6c 331 ::free (v);
332 v = NULL;
2b15d2ba 333}
334
335
f1f41a6c 336/* Allocator type for GC vectors. Notice that we need the structure
337 declaration even if GC is not enabled. */
2b15d2ba 338
f1f41a6c 339struct va_gc
2b15d2ba 340{
f1f41a6c 341 /* Use vl_embed as the default layout for GC vectors. Due to GTY
342 limitations, GC vectors must always be pointers, so it is more
343 efficient to use a pointer to the vl_embed layout, rather than
344 using a pointer to a pointer as would be the case with vl_ptr. */
345 typedef vl_embed default_layout;
346
347 template<typename T, typename A>
348 static void reserve (vec<T, A, vl_embed> *&, unsigned, bool
349 CXX_MEM_STAT_INFO);
350
351 template<typename T, typename A>
182e7ecd 352 static void release (vec<T, A, vl_embed> *&v);
f1f41a6c 353};
2b15d2ba 354
2b15d2ba 355
182e7ecd 356/* Free GC memory used by V and reset V to NULL. */
357
358template<typename T, typename A>
359inline void
360va_gc::release (vec<T, A, vl_embed> *&v)
361{
362 if (v)
363 ::ggc_free (v);
364 v = NULL;
365}
366
367
f1f41a6c 368/* Allocator for GC memory. Ensure there are at least RESERVE free
369 slots in V. If EXACT is true, grow exactly, else grow
370 exponentially. As a special case, if the vector had not been
371 allocated and and RESERVE is 0, no vector will be created. */
372
373template<typename T, typename A>
2b15d2ba 374void
f1f41a6c 375va_gc::reserve (vec<T, A, vl_embed> *&v, unsigned reserve, bool exact
376 MEM_STAT_DECL)
2b15d2ba 377{
cac0c158 378 unsigned alloc
fd3aba29 379 = vec_prefix::calculate_allocation (v ? &v->m_vecpfx : 0, reserve, exact);
f1f41a6c 380 if (!alloc)
381 {
382 ::ggc_free (v);
383 v = NULL;
384 return;
385 }
2b15d2ba 386
f1f41a6c 387 /* Calculate the amount of space we want. */
388 size_t size = vec<T, A, vl_embed>::embedded_size (alloc);
2b15d2ba 389
f1f41a6c 390 /* Ask the allocator how much space it will really give us. */
29c697ae 391 size = ::ggc_round_alloc_size (size);
2b15d2ba 392
f1f41a6c 393 /* Adjust the number of slots accordingly. */
394 size_t vec_offset = sizeof (vec_prefix);
395 size_t elt_size = sizeof (T);
396 alloc = (size - vec_offset) / elt_size;
2b15d2ba 397
f1f41a6c 398 /* And finally, recalculate the amount of space we ask for. */
399 size = vec_offset + alloc * elt_size;
2b15d2ba 400
f1f41a6c 401 unsigned nelem = v ? v->length () : 0;
881f903e 402 v = static_cast <vec<T, A, vl_embed> *> (::ggc_realloc (v, size
29c697ae 403 PASS_MEM_STAT));
f1f41a6c 404 v->embedded_init (alloc, nelem);
405}
190183c5 406
190183c5 407
f1f41a6c 408/* Allocator type for GC vectors. This is for vectors of types
409 atomics w.r.t. collection, so allocation and deallocation is
410 completely inherited from va_gc. */
411struct va_gc_atomic : va_gc
412{
413};
930bdacf 414
2b15d2ba 415
f1f41a6c 416/* Generic vector template. Default values for A and L indicate the
417 most commonly used strategies.
de2b4872 418
f1f41a6c 419 FIXME - Ideally, they would all be vl_ptr to encourage using regular
420 instances for vectors, but the existing GTY machinery is limited
421 in that it can only deal with GC objects that are pointers
422 themselves.
de2b4872 423
f1f41a6c 424 This means that vector operations that need to deal with
425 potentially NULL pointers, must be provided as free
426 functions (see the vec_safe_* functions above). */
427template<typename T,
428 typename A = va_heap,
429 typename L = typename A::default_layout>
29c697ae 430struct GTY((user)) vec
f1f41a6c 431{
432};
de2b4872 433
1e094109 434/* Type to provide NULL values for vec<T, A, L>. This is used to
435 provide nil initializers for vec instances. Since vec must be
436 a POD, we cannot have proper ctor/dtor for it. To initialize
437 a vec instance, you can assign it the value vNULL. */
438struct vnull
439{
440 template <typename T, typename A, typename L>
441 operator vec<T, A, L> () { return vec<T, A, L>(); }
442};
443extern vnull vNULL;
444
de2b4872 445
f1f41a6c 446/* Embeddable vector. These vectors are suitable to be embedded
447 in other data structures so that they can be pre-allocated in a
448 contiguous memory block.
de2b4872 449
f1f41a6c 450 Embeddable vectors are implemented using the trailing array idiom,
451 thus they are not resizeable without changing the address of the
452 vector object itself. This means you cannot have variables or
453 fields of embeddable vector type -- always use a pointer to a
454 vector. The one exception is the final field of a structure, which
455 could be a vector type.
de2b4872 456
f1f41a6c 457 You will have to use the embedded_size & embedded_init calls to
458 create such objects, and they will not be resizeable (so the 'safe'
459 allocation variants are not available).
460
461 Properties:
462
463 - The whole vector and control data are allocated in a single
464 contiguous block. It uses the trailing-vector idiom, so
465 allocation must reserve enough space for all the elements
466 in the vector plus its control data.
467 - The vector cannot be re-allocated.
468 - The vector cannot grow nor shrink.
469 - No indirections needed for access/manipulation.
470 - It requires 2 words of storage (prior to vector allocation). */
471
472template<typename T, typename A>
29c697ae 473struct GTY((user)) vec<T, A, vl_embed>
f1f41a6c 474{
475public:
fd3aba29 476 unsigned allocated (void) const { return m_vecpfx.m_alloc; }
477 unsigned length (void) const { return m_vecpfx.m_num; }
478 bool is_empty (void) const { return m_vecpfx.m_num == 0; }
479 T *address (void) { return m_vecdata; }
480 const T *address (void) const { return m_vecdata; }
f1f41a6c 481 const T &operator[] (unsigned) const;
482 T &operator[] (unsigned);
483 T &last (void);
484 bool space (unsigned) const;
485 bool iterate (unsigned, T *) const;
486 bool iterate (unsigned, T **) const;
29c697ae 487 vec *copy (ALONE_CXX_MEM_STAT_INFO) const;
103be950 488 void splice (const vec &);
489 void splice (const vec *src);
f1f41a6c 490 T *quick_push (const T &);
491 T &pop (void);
492 void truncate (unsigned);
493 void quick_insert (unsigned, const T &);
494 void ordered_remove (unsigned);
495 void unordered_remove (unsigned);
496 void block_remove (unsigned, unsigned);
497 void qsort (int (*) (const void *, const void *));
3e48928c 498 T *bsearch (const void *key, int (*compar)(const void *, const void *));
f1f41a6c 499 unsigned lower_bound (T, bool (*)(const T &, const T &)) const;
500 static size_t embedded_size (unsigned);
ec456ba8 501 void embedded_init (unsigned, unsigned = 0, unsigned = 0);
f1f41a6c 502 void quick_grow (unsigned len);
503 void quick_grow_cleared (unsigned len);
504
505 /* vec class can access our internal data and functions. */
29c697ae 506 template <typename, typename, typename> friend struct vec;
f1f41a6c 507
508 /* The allocator types also need access to our internals. */
509 friend struct va_gc;
510 friend struct va_gc_atomic;
511 friend struct va_heap;
f1f41a6c 512
aad734b2 513 /* FIXME - These fields should be private, but we need to cater to
514 compilers that have stricter notions of PODness for types. */
fd3aba29 515 vec_prefix m_vecpfx;
516 T m_vecdata[1];
f1f41a6c 517};
de2b4872 518
de2b4872 519
f1f41a6c 520/* Convenience wrapper functions to use when dealing with pointers to
521 embedded vectors. Some functionality for these vectors must be
522 provided via free functions for these reasons:
2b15d2ba 523
f1f41a6c 524 1- The pointer may be NULL (e.g., before initial allocation).
2b15d2ba 525
f1f41a6c 526 2- When the vector needs to grow, it must be reallocated, so
527 the pointer will change its value.
2b15d2ba 528
f1f41a6c 529 Because of limitations with the current GC machinery, all vectors
530 in GC memory *must* be pointers. */
2b15d2ba 531
de2b4872 532
f1f41a6c 533/* If V contains no room for NELEMS elements, return false. Otherwise,
534 return true. */
535template<typename T, typename A>
536inline bool
537vec_safe_space (const vec<T, A, vl_embed> *v, unsigned nelems)
538{
539 return v ? v->space (nelems) : nelems == 0;
540}
de2b4872 541
2b15d2ba 542
f1f41a6c 543/* If V is NULL, return 0. Otherwise, return V->length(). */
544template<typename T, typename A>
de2b4872 545inline unsigned
f1f41a6c 546vec_safe_length (const vec<T, A, vl_embed> *v)
2b15d2ba 547{
f1f41a6c 548 return v ? v->length () : 0;
2b15d2ba 549}
c75b4594 550
551
f1f41a6c 552/* If V is NULL, return NULL. Otherwise, return V->address(). */
553template<typename T, typename A>
554inline T *
555vec_safe_address (vec<T, A, vl_embed> *v)
556{
557 return v ? v->address () : NULL;
558}
559
de2b4872 560
f1f41a6c 561/* If V is NULL, return true. Otherwise, return V->is_empty(). */
562template<typename T, typename A>
de2b4872 563inline bool
f1f41a6c 564vec_safe_is_empty (vec<T, A, vl_embed> *v)
de2b4872 565{
f1f41a6c 566 return v ? v->is_empty () : true;
de2b4872 567}
190183c5 568
930bdacf 569
f1f41a6c 570/* If V does not have space for NELEMS elements, call
571 V->reserve(NELEMS, EXACT). */
572template<typename T, typename A>
573inline bool
574vec_safe_reserve (vec<T, A, vl_embed> *&v, unsigned nelems, bool exact = false
29c697ae 575 CXX_MEM_STAT_INFO)
f1f41a6c 576{
577 bool extend = nelems ? !vec_safe_space (v, nelems) : false;
578 if (extend)
579 A::reserve (v, nelems, exact PASS_MEM_STAT);
580 return extend;
581}
2b15d2ba 582
f1f41a6c 583template<typename T, typename A>
584inline bool
29c697ae 585vec_safe_reserve_exact (vec<T, A, vl_embed> *&v, unsigned nelems
586 CXX_MEM_STAT_INFO)
2b15d2ba 587{
f1f41a6c 588 return vec_safe_reserve (v, nelems, true PASS_MEM_STAT);
2b15d2ba 589}
590
190183c5 591
f1f41a6c 592/* Allocate GC memory for V with space for NELEMS slots. If NELEMS
593 is 0, V is initialized to NULL. */
de2b4872 594
f1f41a6c 595template<typename T, typename A>
596inline void
29c697ae 597vec_alloc (vec<T, A, vl_embed> *&v, unsigned nelems CXX_MEM_STAT_INFO)
de2b4872 598{
f1f41a6c 599 v = NULL;
29c697ae 600 vec_safe_reserve (v, nelems, false PASS_MEM_STAT);
de2b4872 601}
190183c5 602
2b15d2ba 603
f1f41a6c 604/* Free the GC memory allocated by vector V and set it to NULL. */
2b15d2ba 605
f1f41a6c 606template<typename T, typename A>
607inline void
608vec_free (vec<T, A, vl_embed> *&v)
2b15d2ba 609{
f1f41a6c 610 A::release (v);
2b15d2ba 611}
612
f1f41a6c 613
614/* Grow V to length LEN. Allocate it, if necessary. */
615template<typename T, typename A>
616inline void
29c697ae 617vec_safe_grow (vec<T, A, vl_embed> *&v, unsigned len CXX_MEM_STAT_INFO)
2b15d2ba 618{
f1f41a6c 619 unsigned oldlen = vec_safe_length (v);
620 gcc_checking_assert (len >= oldlen);
621 vec_safe_reserve_exact (v, len - oldlen PASS_MEM_STAT);
29c697ae 622 v->quick_grow (len);
2b15d2ba 623}
930bdacf 624
190183c5 625
f1f41a6c 626/* If V is NULL, allocate it. Call V->safe_grow_cleared(LEN). */
627template<typename T, typename A>
628inline void
29c697ae 629vec_safe_grow_cleared (vec<T, A, vl_embed> *&v, unsigned len CXX_MEM_STAT_INFO)
f1f41a6c 630{
631 unsigned oldlen = vec_safe_length (v);
632 vec_safe_grow (v, len PASS_MEM_STAT);
9af5ce0c 633 memset (&(v->address ()[oldlen]), 0, sizeof (T) * (len - oldlen));
f1f41a6c 634}
190183c5 635
2b15d2ba 636
f1f41a6c 637/* If V is NULL return false, otherwise return V->iterate(IX, PTR). */
638template<typename T, typename A>
639inline bool
640vec_safe_iterate (const vec<T, A, vl_embed> *v, unsigned ix, T **ptr)
2b15d2ba 641{
f1f41a6c 642 if (v)
643 return v->iterate (ix, ptr);
2b15d2ba 644 else
645 {
646 *ptr = 0;
647 return false;
648 }
649}
650
f1f41a6c 651template<typename T, typename A>
652inline bool
653vec_safe_iterate (const vec<T, A, vl_embed> *v, unsigned ix, T *ptr)
2b15d2ba 654{
f1f41a6c 655 if (v)
656 return v->iterate (ix, ptr);
2b15d2ba 657 else
658 {
659 *ptr = 0;
660 return false;
661 }
662}
190183c5 663
de2b4872 664
f1f41a6c 665/* If V has no room for one more element, reallocate it. Then call
666 V->quick_push(OBJ). */
667template<typename T, typename A>
668inline T *
29c697ae 669vec_safe_push (vec<T, A, vl_embed> *&v, const T &obj CXX_MEM_STAT_INFO)
f1f41a6c 670{
671 vec_safe_reserve (v, 1, false PASS_MEM_STAT);
29c697ae 672 return v->quick_push (obj);
f1f41a6c 673}
48148244 674
48148244 675
f1f41a6c 676/* if V has no room for one more element, reallocate it. Then call
677 V->quick_insert(IX, OBJ). */
678template<typename T, typename A>
679inline void
680vec_safe_insert (vec<T, A, vl_embed> *&v, unsigned ix, const T &obj
29c697ae 681 CXX_MEM_STAT_INFO)
f1f41a6c 682{
683 vec_safe_reserve (v, 1, false PASS_MEM_STAT);
684 v->quick_insert (ix, obj);
685}
31adcf56 686
31adcf56 687
f1f41a6c 688/* If V is NULL, do nothing. Otherwise, call V->truncate(SIZE). */
689template<typename T, typename A>
690inline void
691vec_safe_truncate (vec<T, A, vl_embed> *v, unsigned size)
692{
693 if (v)
694 v->truncate (size);
695}
2ab2ce89 696
2ab2ce89 697
f1f41a6c 698/* If SRC is not NULL, return a pointer to a copy of it. */
699template<typename T, typename A>
700inline vec<T, A, vl_embed> *
ea7d8c7a 701vec_safe_copy (vec<T, A, vl_embed> *src CXX_MEM_STAT_INFO)
f1f41a6c 702{
ea7d8c7a 703 return src ? src->copy (ALONE_PASS_MEM_STAT) : NULL;
f1f41a6c 704}
2b15d2ba 705
f1f41a6c 706/* Copy the elements from SRC to the end of DST as if by memcpy.
707 Reallocate DST, if necessary. */
708template<typename T, typename A>
709inline void
103be950 710vec_safe_splice (vec<T, A, vl_embed> *&dst, const vec<T, A, vl_embed> *src
29c697ae 711 CXX_MEM_STAT_INFO)
f1f41a6c 712{
713 unsigned src_len = vec_safe_length (src);
714 if (src_len)
715 {
29c697ae 716 vec_safe_reserve_exact (dst, vec_safe_length (dst) + src_len
717 PASS_MEM_STAT);
f1f41a6c 718 dst->splice (*src);
719 }
720}
2b15d2ba 721
2b15d2ba 722
f1f41a6c 723/* Index into vector. Return the IX'th element. IX must be in the
724 domain of the vector. */
2b15d2ba 725
f1f41a6c 726template<typename T, typename A>
727inline const T &
728vec<T, A, vl_embed>::operator[] (unsigned ix) const
729{
fd3aba29 730 gcc_checking_assert (ix < m_vecpfx.m_num);
731 return m_vecdata[ix];
f1f41a6c 732}
2b15d2ba 733
f1f41a6c 734template<typename T, typename A>
735inline T &
736vec<T, A, vl_embed>::operator[] (unsigned ix)
2b15d2ba 737{
fd3aba29 738 gcc_checking_assert (ix < m_vecpfx.m_num);
739 return m_vecdata[ix];
2b15d2ba 740}
741
de2b4872 742
f1f41a6c 743/* Get the final element of the vector, which must not be empty. */
2b15d2ba 744
f1f41a6c 745template<typename T, typename A>
746inline T &
747vec<T, A, vl_embed>::last (void)
2b15d2ba 748{
fd3aba29 749 gcc_checking_assert (m_vecpfx.m_num > 0);
750 return (*this)[m_vecpfx.m_num - 1];
2b15d2ba 751}
752
753
f1f41a6c 754/* If this vector has space for NELEMS additional entries, return
755 true. You usually only need to use this if you are doing your
756 own vector reallocation, for instance on an embedded vector. This
757 returns true in exactly the same circumstances that vec::reserve
758 will. */
de2b4872 759
f1f41a6c 760template<typename T, typename A>
761inline bool
762vec<T, A, vl_embed>::space (unsigned nelems) const
763{
fd3aba29 764 return m_vecpfx.m_alloc - m_vecpfx.m_num >= nelems;
f1f41a6c 765}
de2b4872 766
de2b4872 767
f1f41a6c 768/* Return iteration condition and update PTR to point to the IX'th
769 element of this vector. Use this to iterate over the elements of a
770 vector as follows,
de2b4872 771
9af5ce0c 772 for (ix = 0; vec<T, A>::iterate (v, ix, &ptr); ix++)
f1f41a6c 773 continue; */
de2b4872 774
f1f41a6c 775template<typename T, typename A>
776inline bool
777vec<T, A, vl_embed>::iterate (unsigned ix, T *ptr) const
2b15d2ba 778{
fd3aba29 779 if (ix < m_vecpfx.m_num)
f1f41a6c 780 {
fd3aba29 781 *ptr = m_vecdata[ix];
f1f41a6c 782 return true;
783 }
784 else
785 {
786 *ptr = 0;
787 return false;
788 }
2b15d2ba 789}
790
930bdacf 791
f1f41a6c 792/* Return iteration condition and update *PTR to point to the
793 IX'th element of this vector. Use this to iterate over the
794 elements of a vector as follows,
190183c5 795
9af5ce0c 796 for (ix = 0; v->iterate (ix, &ptr); ix++)
f1f41a6c 797 continue;
07e8c04c 798
f1f41a6c 799 This variant is for vectors of objects. */
800
801template<typename T, typename A>
802inline bool
803vec<T, A, vl_embed>::iterate (unsigned ix, T **ptr) const
2b15d2ba 804{
fd3aba29 805 if (ix < m_vecpfx.m_num)
f1f41a6c 806 {
fd3aba29 807 *ptr = CONST_CAST (T *, &m_vecdata[ix]);
f1f41a6c 808 return true;
809 }
810 else
2b15d2ba 811 {
f1f41a6c 812 *ptr = 0;
813 return false;
2b15d2ba 814 }
2b15d2ba 815}
930bdacf 816
930bdacf 817
f1f41a6c 818/* Return a pointer to a copy of this vector. */
c75b4594 819
f1f41a6c 820template<typename T, typename A>
821inline vec<T, A, vl_embed> *
822vec<T, A, vl_embed>::copy (ALONE_MEM_STAT_DECL) const
2b15d2ba 823{
f1f41a6c 824 vec<T, A, vl_embed> *new_vec = NULL;
825 unsigned len = length ();
de2b4872 826 if (len)
2b15d2ba 827 {
f1f41a6c 828 vec_alloc (new_vec, len PASS_MEM_STAT);
de2b4872 829 new_vec->embedded_init (len, len);
fd3aba29 830 memcpy (new_vec->address (), m_vecdata, sizeof (T) * len);
2b15d2ba 831 }
de2b4872 832 return new_vec;
833}
48e1416a 834
930bdacf 835
f1f41a6c 836/* Copy the elements from SRC to the end of this vector as if by memcpy.
837 The vector must have sufficient headroom available. */
930bdacf 838
f1f41a6c 839template<typename T, typename A>
840inline void
103be950 841vec<T, A, vl_embed>::splice (const vec<T, A, vl_embed> &src)
f1f41a6c 842{
9af5ce0c 843 unsigned len = src.length ();
f1f41a6c 844 if (len)
845 {
846 gcc_checking_assert (space (len));
9af5ce0c 847 memcpy (address () + length (), src.address (), len * sizeof (T));
fd3aba29 848 m_vecpfx.m_num += len;
f1f41a6c 849 }
850}
851
852template<typename T, typename A>
853inline void
103be950 854vec<T, A, vl_embed>::splice (const vec<T, A, vl_embed> *src)
2b15d2ba 855{
f1f41a6c 856 if (src)
857 splice (*src);
2b15d2ba 858}
859
190183c5 860
f1f41a6c 861/* Push OBJ (a new element) onto the end of the vector. There must be
862 sufficient space in the vector. Return a pointer to the slot
863 where OBJ was inserted. */
930bdacf 864
f1f41a6c 865template<typename T, typename A>
866inline T *
867vec<T, A, vl_embed>::quick_push (const T &obj)
2b15d2ba 868{
f1f41a6c 869 gcc_checking_assert (space (1));
fd3aba29 870 T *slot = &m_vecdata[m_vecpfx.m_num++];
f1f41a6c 871 *slot = obj;
872 return slot;
2b15d2ba 873}
874
190183c5 875
f1f41a6c 876/* Pop and return the last element off the end of the vector. */
24ffec38 877
f1f41a6c 878template<typename T, typename A>
879inline T &
880vec<T, A, vl_embed>::pop (void)
2b15d2ba 881{
f1f41a6c 882 gcc_checking_assert (length () > 0);
fd3aba29 883 return m_vecdata[--m_vecpfx.m_num];
f1f41a6c 884}
2b15d2ba 885
2b15d2ba 886
f1f41a6c 887/* Set the length of the vector to SIZE. The new length must be less
888 than or equal to the current length. This is an O(1) operation. */
889
890template<typename T, typename A>
891inline void
892vec<T, A, vl_embed>::truncate (unsigned size)
893{
894 gcc_checking_assert (length () >= size);
fd3aba29 895 m_vecpfx.m_num = size;
2b15d2ba 896}
897
24ffec38 898
f1f41a6c 899/* Insert an element, OBJ, at the IXth position of this vector. There
900 must be sufficient space. */
2b15d2ba 901
f1f41a6c 902template<typename T, typename A>
903inline void
904vec<T, A, vl_embed>::quick_insert (unsigned ix, const T &obj)
2b15d2ba 905{
f1f41a6c 906 gcc_checking_assert (length () < allocated ());
907 gcc_checking_assert (ix <= length ());
fd3aba29 908 T *slot = &m_vecdata[ix];
909 memmove (slot + 1, slot, (m_vecpfx.m_num++ - ix) * sizeof (T));
f1f41a6c 910 *slot = obj;
2b15d2ba 911}
912
008f96d8 913
f1f41a6c 914/* Remove an element from the IXth position of this vector. Ordering of
915 remaining elements is preserved. This is an O(N) operation due to
916 memmove. */
008f96d8 917
f1f41a6c 918template<typename T, typename A>
919inline void
920vec<T, A, vl_embed>::ordered_remove (unsigned ix)
2b15d2ba 921{
9af5ce0c 922 gcc_checking_assert (ix < length ());
fd3aba29 923 T *slot = &m_vecdata[ix];
924 memmove (slot, slot + 1, (--m_vecpfx.m_num - ix) * sizeof (T));
f1f41a6c 925}
926
927
928/* Remove an element from the IXth position of this vector. Ordering of
929 remaining elements is destroyed. This is an O(1) operation. */
930
931template<typename T, typename A>
932inline void
933vec<T, A, vl_embed>::unordered_remove (unsigned ix)
934{
9af5ce0c 935 gcc_checking_assert (ix < length ());
fd3aba29 936 m_vecdata[ix] = m_vecdata[--m_vecpfx.m_num];
f1f41a6c 937}
938
939
940/* Remove LEN elements starting at the IXth. Ordering is retained.
941 This is an O(N) operation due to memmove. */
942
943template<typename T, typename A>
944inline void
945vec<T, A, vl_embed>::block_remove (unsigned ix, unsigned len)
946{
9af5ce0c 947 gcc_checking_assert (ix + len <= length ());
fd3aba29 948 T *slot = &m_vecdata[ix];
949 m_vecpfx.m_num -= len;
950 memmove (slot, slot + len, (m_vecpfx.m_num - ix) * sizeof (T));
f1f41a6c 951}
952
953
954/* Sort the contents of this vector with qsort. CMP is the comparison
955 function to pass to qsort. */
956
957template<typename T, typename A>
958inline void
959vec<T, A, vl_embed>::qsort (int (*cmp) (const void *, const void *))
960{
3e48928c 961 if (length () > 1)
962 ::qsort (address (), length (), sizeof (T), cmp);
963}
964
965
966/* Search the contents of the sorted vector with a binary search.
967 CMP is the comparison function to pass to bsearch. */
968
969template<typename T, typename A>
970inline T *
971vec<T, A, vl_embed>::bsearch (const void *key,
972 int (*compar) (const void *, const void *))
973{
974 const void *base = this->address ();
975 size_t nmemb = this->length ();
976 size_t size = sizeof (T);
977 /* The following is a copy of glibc stdlib-bsearch.h. */
978 size_t l, u, idx;
979 const void *p;
980 int comparison;
981
982 l = 0;
983 u = nmemb;
984 while (l < u)
985 {
986 idx = (l + u) / 2;
987 p = (const void *) (((const char *) base) + (idx * size));
988 comparison = (*compar) (key, p);
989 if (comparison < 0)
990 u = idx;
991 else if (comparison > 0)
992 l = idx + 1;
993 else
994 return (T *)const_cast<void *>(p);
995 }
996
997 return NULL;
f1f41a6c 998}
999
1000
1001/* Find and return the first position in which OBJ could be inserted
1002 without changing the ordering of this vector. LESSTHAN is a
1003 function that returns true if the first argument is strictly less
1004 than the second. */
1005
1006template<typename T, typename A>
1007unsigned
1008vec<T, A, vl_embed>::lower_bound (T obj, bool (*lessthan)(const T &, const T &))
1009 const
1010{
1011 unsigned int len = length ();
1012 unsigned int half, middle;
1013 unsigned int first = 0;
1014 while (len > 0)
2b15d2ba 1015 {
f1f41a6c 1016 half = len / 2;
1017 middle = first;
1018 middle += half;
1019 T middle_elem = (*this)[middle];
1020 if (lessthan (middle_elem, obj))
1021 {
1022 first = middle;
1023 ++first;
1024 len = len - half - 1;
1025 }
1026 else
1027 len = half;
2b15d2ba 1028 }
f1f41a6c 1029 return first;
2b15d2ba 1030}
1031
2b15d2ba 1032
f1f41a6c 1033/* Return the number of bytes needed to embed an instance of an
1034 embeddable vec inside another data structure.
de2b4872 1035
f1f41a6c 1036 Use these methods to determine the required size and initialization
1037 of a vector V of type T embedded within another structure (as the
1038 final member):
1039
1040 size_t vec<T, A, vl_embed>::embedded_size (unsigned alloc);
9af5ce0c 1041 void v->embedded_init (unsigned alloc, unsigned num);
f1f41a6c 1042
1043 These allow the caller to perform the memory allocation. */
1044
1045template<typename T, typename A>
1046inline size_t
1047vec<T, A, vl_embed>::embedded_size (unsigned alloc)
2b15d2ba 1048{
f1f41a6c 1049 typedef vec<T, A, vl_embed> vec_embedded;
fd3aba29 1050 return offsetof (vec_embedded, m_vecdata) + alloc * sizeof (T);
2b15d2ba 1051}
1052
190183c5 1053
f1f41a6c 1054/* Initialize the vector to contain room for ALLOC elements and
1055 NUM active elements. */
de2b4872 1056
f1f41a6c 1057template<typename T, typename A>
1058inline void
ec456ba8 1059vec<T, A, vl_embed>::embedded_init (unsigned alloc, unsigned num, unsigned aut)
2b15d2ba 1060{
fd3aba29 1061 m_vecpfx.m_alloc = alloc;
ec456ba8 1062 m_vecpfx.m_using_auto_storage = aut;
fd3aba29 1063 m_vecpfx.m_num = num;
2b15d2ba 1064}
1065
190183c5 1066
f1f41a6c 1067/* Grow the vector to a specific length. LEN must be as long or longer than
1068 the current length. The new elements are uninitialized. */
2b15d2ba 1069
f1f41a6c 1070template<typename T, typename A>
1071inline void
1072vec<T, A, vl_embed>::quick_grow (unsigned len)
2b15d2ba 1073{
fd3aba29 1074 gcc_checking_assert (length () <= len && len <= m_vecpfx.m_alloc);
1075 m_vecpfx.m_num = len;
2b15d2ba 1076}
1077
190183c5 1078
f1f41a6c 1079/* Grow the vector to a specific length. LEN must be as long or longer than
1080 the current length. The new elements are initialized to zero. */
2b15d2ba 1081
f1f41a6c 1082template<typename T, typename A>
1083inline void
1084vec<T, A, vl_embed>::quick_grow_cleared (unsigned len)
2b15d2ba 1085{
f1f41a6c 1086 unsigned oldlen = length ();
1087 quick_grow (len);
9af5ce0c 1088 memset (&(address ()[oldlen]), 0, sizeof (T) * (len - oldlen));
2b15d2ba 1089}
1090
046bfc77 1091
f1f41a6c 1092/* Garbage collection support for vec<T, A, vl_embed>. */
046bfc77 1093
de2b4872 1094template<typename T>
de2b4872 1095void
f1f41a6c 1096gt_ggc_mx (vec<T, va_gc> *v)
2b15d2ba 1097{
f1f41a6c 1098 extern void gt_ggc_mx (T &);
1099 for (unsigned i = 0; i < v->length (); i++)
1100 gt_ggc_mx ((*v)[i]);
2b15d2ba 1101}
1102
de2b4872 1103template<typename T>
de2b4872 1104void
f1f41a6c 1105gt_ggc_mx (vec<T, va_gc_atomic, vl_embed> *v ATTRIBUTE_UNUSED)
2b15d2ba 1106{
f1f41a6c 1107 /* Nothing to do. Vectors of atomic types wrt GC do not need to
1108 be traversed. */
2b15d2ba 1109}
1110
e85c2c2d 1111
f1f41a6c 1112/* PCH support for vec<T, A, vl_embed>. */
2b15d2ba 1113
f1f41a6c 1114template<typename T, typename A>
de2b4872 1115void
f1f41a6c 1116gt_pch_nx (vec<T, A, vl_embed> *v)
2b15d2ba 1117{
f1f41a6c 1118 extern void gt_pch_nx (T &);
1119 for (unsigned i = 0; i < v->length (); i++)
1120 gt_pch_nx ((*v)[i]);
2b15d2ba 1121}
1122
f1f41a6c 1123template<typename T, typename A>
1124void
1125gt_pch_nx (vec<T *, A, vl_embed> *v, gt_pointer_operator op, void *cookie)
1126{
1127 for (unsigned i = 0; i < v->length (); i++)
1128 op (&((*v)[i]), cookie);
1129}
190183c5 1130
f1f41a6c 1131template<typename T, typename A>
de2b4872 1132void
f1f41a6c 1133gt_pch_nx (vec<T, A, vl_embed> *v, gt_pointer_operator op, void *cookie)
de2b4872 1134{
f1f41a6c 1135 extern void gt_pch_nx (T *, gt_pointer_operator, void *);
1136 for (unsigned i = 0; i < v->length (); i++)
1137 gt_pch_nx (&((*v)[i]), op, cookie);
de2b4872 1138}
930bdacf 1139
de2b4872 1140
f1f41a6c 1141/* Space efficient vector. These vectors can grow dynamically and are
1142 allocated together with their control data. They are suited to be
1143 included in data structures. Prior to initial allocation, they
1144 only take a single word of storage.
1145
1146 These vectors are implemented as a pointer to an embeddable vector.
1147 The semantics allow for this pointer to be NULL to represent empty
1148 vectors. This way, empty vectors occupy minimal space in the
1149 structure containing them.
1150
1151 Properties:
1152
1153 - The whole vector and control data are allocated in a single
1154 contiguous block.
1155 - The whole vector may be re-allocated.
1156 - Vector data may grow and shrink.
1157 - Access and manipulation requires a pointer test and
1158 indirection.
1159 - It requires 1 word of storage (prior to vector allocation).
1160
1161
1162 Limitations:
1163
1164 These vectors must be PODs because they are stored in unions.
1165 (http://en.wikipedia.org/wiki/Plain_old_data_structures).
1166 As long as we use C++03, we cannot have constructors nor
1167 destructors in classes that are stored in unions. */
1168
d70aebca 1169template<typename T>
1170struct vec<T, va_heap, vl_ptr>
f1f41a6c 1171{
1172public:
1173 /* Memory allocation and deallocation for the embedded vector.
1174 Needed because we cannot have proper ctors/dtors defined. */
1175 void create (unsigned nelems CXX_MEM_STAT_INFO);
1176 void release (void);
1177
1178 /* Vector operations. */
1179 bool exists (void) const
fd3aba29 1180 { return m_vec != NULL; }
f1f41a6c 1181
1182 bool is_empty (void) const
fd3aba29 1183 { return m_vec ? m_vec->is_empty () : true; }
f1f41a6c 1184
1185 unsigned length (void) const
fd3aba29 1186 { return m_vec ? m_vec->length () : 0; }
f1f41a6c 1187
1188 T *address (void)
fd3aba29 1189 { return m_vec ? m_vec->m_vecdata : NULL; }
f1f41a6c 1190
1191 const T *address (void) const
fd3aba29 1192 { return m_vec ? m_vec->m_vecdata : NULL; }
f1f41a6c 1193
1194 const T &operator[] (unsigned ix) const
fd3aba29 1195 { return (*m_vec)[ix]; }
f1f41a6c 1196
1197 bool operator!=(const vec &other) const
1198 { return !(*this == other); }
1199
1200 bool operator==(const vec &other) const
9af5ce0c 1201 { return address () == other.address (); }
f1f41a6c 1202
1203 T &operator[] (unsigned ix)
fd3aba29 1204 { return (*m_vec)[ix]; }
f1f41a6c 1205
1206 T &last (void)
fd3aba29 1207 { return m_vec->last (); }
f1f41a6c 1208
1209 bool space (int nelems) const
fd3aba29 1210 { return m_vec ? m_vec->space (nelems) : nelems == 0; }
f1f41a6c 1211
1212 bool iterate (unsigned ix, T *p) const;
1213 bool iterate (unsigned ix, T **p) const;
1214 vec copy (ALONE_CXX_MEM_STAT_INFO) const;
1215 bool reserve (unsigned, bool = false CXX_MEM_STAT_INFO);
1216 bool reserve_exact (unsigned CXX_MEM_STAT_INFO);
103be950 1217 void splice (const vec &);
1218 void safe_splice (const vec & CXX_MEM_STAT_INFO);
f1f41a6c 1219 T *quick_push (const T &);
1220 T *safe_push (const T &CXX_MEM_STAT_INFO);
1221 T &pop (void);
1222 void truncate (unsigned);
1223 void safe_grow (unsigned CXX_MEM_STAT_INFO);
1224 void safe_grow_cleared (unsigned CXX_MEM_STAT_INFO);
1225 void quick_grow (unsigned);
1226 void quick_grow_cleared (unsigned);
1227 void quick_insert (unsigned, const T &);
1228 void safe_insert (unsigned, const T & CXX_MEM_STAT_INFO);
1229 void ordered_remove (unsigned);
1230 void unordered_remove (unsigned);
1231 void block_remove (unsigned, unsigned);
1232 void qsort (int (*) (const void *, const void *));
3e48928c 1233 T *bsearch (const void *key, int (*compar)(const void *, const void *));
f1f41a6c 1234 unsigned lower_bound (T, bool (*)(const T &, const T &)) const;
1235
d70aebca 1236 bool using_auto_storage () const;
f1f41a6c 1237
aad734b2 1238 /* FIXME - This field should be private, but we need to cater to
1239 compilers that have stricter notions of PODness for types. */
d70aebca 1240 vec<T, va_heap, vl_embed> *m_vec;
f1f41a6c 1241};
1242
1243
4997014d 1244/* auto_vec is a subclass of vec that automatically manages creating and
1245 releasing the internal vector. If N is non zero then it has N elements of
1246 internal storage. The default is no internal storage, and you probably only
1247 want to ask for internal storage for vectors on the stack because if the
1248 size of the vector is larger than the internal storage that space is wasted.
1249 */
1250template<typename T, size_t N = 0>
c2078b80 1251class auto_vec : public vec<T, va_heap>
1252{
1253public:
4997014d 1254 auto_vec ()
d70aebca 1255 {
ec456ba8 1256 m_auto.embedded_init (MAX (N, 2), 0, 1);
1257 this->m_vec = &m_auto;
d70aebca 1258 }
1259
4997014d 1260 ~auto_vec ()
d70aebca 1261 {
1262 this->release ();
1263 }
1264
1265private:
ec456ba8 1266 vec<T, va_heap, vl_embed> m_auto;
1267 T m_data[MAX (N - 1, 1)];
f1f41a6c 1268};
2b15d2ba 1269
4997014d 1270/* auto_vec is a sub class of vec whose storage is released when it is
1271 destroyed. */
1272template<typename T>
1273class auto_vec<T, 0> : public vec<T, va_heap>
1274{
1275public:
1276 auto_vec () { this->m_vec = NULL; }
1277 auto_vec (size_t n) { this->create (n); }
1278 ~auto_vec () { this->release (); }
1279};
1280
190183c5 1281
f1f41a6c 1282/* Allocate heap memory for pointer V and create the internal vector
1283 with space for NELEMS elements. If NELEMS is 0, the internal
1284 vector is initialized to empty. */
930bdacf 1285
2b15d2ba 1286template<typename T>
f1f41a6c 1287inline void
29c697ae 1288vec_alloc (vec<T> *&v, unsigned nelems CXX_MEM_STAT_INFO)
2b15d2ba 1289{
f1f41a6c 1290 v = new vec<T>;
1291 v->create (nelems PASS_MEM_STAT);
2b15d2ba 1292}
1293
190183c5 1294
f1f41a6c 1295/* Conditionally allocate heap memory for VEC and its internal vector. */
930bdacf 1296
2b15d2ba 1297template<typename T>
f1f41a6c 1298inline void
29c697ae 1299vec_check_alloc (vec<T, va_heap> *&vec, unsigned nelems CXX_MEM_STAT_INFO)
2b15d2ba 1300{
f1f41a6c 1301 if (!vec)
1302 vec_alloc (vec, nelems PASS_MEM_STAT);
2b15d2ba 1303}
1304
190183c5 1305
f1f41a6c 1306/* Free the heap memory allocated by vector V and set it to NULL. */
dbd44b25 1307
2b15d2ba 1308template<typename T>
f1f41a6c 1309inline void
1310vec_free (vec<T> *&v)
2b15d2ba 1311{
f1f41a6c 1312 if (v == NULL)
1313 return;
1314
1315 v->release ();
1316 delete v;
1317 v = NULL;
2b15d2ba 1318}
930bdacf 1319
de5ab3f1 1320
f1f41a6c 1321/* Return iteration condition and update PTR to point to the IX'th
1322 element of this vector. Use this to iterate over the elements of a
1323 vector as follows,
1324
9af5ce0c 1325 for (ix = 0; v.iterate (ix, &ptr); ix++)
f1f41a6c 1326 continue; */
1327
d70aebca 1328template<typename T>
f1f41a6c 1329inline bool
d70aebca 1330vec<T, va_heap, vl_ptr>::iterate (unsigned ix, T *ptr) const
72e5da43 1331{
fd3aba29 1332 if (m_vec)
1333 return m_vec->iterate (ix, ptr);
f1f41a6c 1334 else
2b15d2ba 1335 {
f1f41a6c 1336 *ptr = 0;
1337 return false;
2b15d2ba 1338 }
4cf7067a 1339}
1340
de2b4872 1341
f1f41a6c 1342/* Return iteration condition and update *PTR to point to the
1343 IX'th element of this vector. Use this to iterate over the
1344 elements of a vector as follows,
1345
9af5ce0c 1346 for (ix = 0; v->iterate (ix, &ptr); ix++)
f1f41a6c 1347 continue;
f7f05a07 1348
f1f41a6c 1349 This variant is for vectors of objects. */
f7f05a07 1350
d70aebca 1351template<typename T>
f1f41a6c 1352inline bool
d70aebca 1353vec<T, va_heap, vl_ptr>::iterate (unsigned ix, T **ptr) const
2b15d2ba 1354{
fd3aba29 1355 if (m_vec)
1356 return m_vec->iterate (ix, ptr);
f1f41a6c 1357 else
de2b4872 1358 {
f1f41a6c 1359 *ptr = 0;
1360 return false;
de2b4872 1361 }
f1f41a6c 1362}
1363
1364
1365/* Convenience macro for forward iteration. */
1366#define FOR_EACH_VEC_ELT(V, I, P) \
1367 for (I = 0; (V).iterate ((I), &(P)); ++(I))
1368
1369#define FOR_EACH_VEC_SAFE_ELT(V, I, P) \
1370 for (I = 0; vec_safe_iterate ((V), (I), &(P)); ++(I))
1371
1372/* Likewise, but start from FROM rather than 0. */
1373#define FOR_EACH_VEC_ELT_FROM(V, I, P, FROM) \
1374 for (I = (FROM); (V).iterate ((I), &(P)); ++(I))
de2b4872 1375
f1f41a6c 1376/* Convenience macro for reverse iteration. */
1377#define FOR_EACH_VEC_ELT_REVERSE(V, I, P) \
1378 for (I = (V).length () - 1; \
1379 (V).iterate ((I), &(P)); \
1380 (I)--)
1381
1382#define FOR_EACH_VEC_SAFE_ELT_REVERSE(V, I, P) \
1383 for (I = vec_safe_length (V) - 1; \
1384 vec_safe_iterate ((V), (I), &(P)); \
1385 (I)--)
1386
1387
1388/* Return a copy of this vector. */
1389
d70aebca 1390template<typename T>
1391inline vec<T, va_heap, vl_ptr>
1392vec<T, va_heap, vl_ptr>::copy (ALONE_MEM_STAT_DECL) const
f1f41a6c 1393{
d70aebca 1394 vec<T, va_heap, vl_ptr> new_vec = vNULL;
f1f41a6c 1395 if (length ())
fd3aba29 1396 new_vec.m_vec = m_vec->copy ();
f1f41a6c 1397 return new_vec;
f7f05a07 1398}
1399
f7f05a07 1400
f1f41a6c 1401/* Ensure that the vector has at least RESERVE slots available (if
1402 EXACT is false), or exactly RESERVE slots available (if EXACT is
1403 true).
f7f05a07 1404
f1f41a6c 1405 This may create additional headroom if EXACT is false.
1406
1407 Note that this can cause the embedded vector to be reallocated.
1408 Returns true iff reallocation actually occurred. */
1409
d70aebca 1410template<typename T>
f1f41a6c 1411inline bool
d70aebca 1412vec<T, va_heap, vl_ptr>::reserve (unsigned nelems, bool exact MEM_STAT_DECL)
1413{
ec456ba8 1414 if (space (nelems))
d70aebca 1415 return false;
1416
1417 /* For now play a game with va_heap::reserve to hide our auto storage if any,
1418 this is necessary because it doesn't have enough information to know the
1419 embedded vector is in auto storage, and so should not be freed. */
1420 vec<T, va_heap, vl_embed> *oldvec = m_vec;
1421 unsigned int oldsize = 0;
1422 bool handle_auto_vec = m_vec && using_auto_storage ();
1423 if (handle_auto_vec)
1424 {
1425 m_vec = NULL;
1426 oldsize = oldvec->length ();
1427 nelems += oldsize;
1428 }
1429
1430 va_heap::reserve (m_vec, nelems, exact PASS_MEM_STAT);
1431 if (handle_auto_vec)
1432 {
1433 memcpy (m_vec->address (), oldvec->address (), sizeof (T) * oldsize);
1434 m_vec->m_vecpfx.m_num = oldsize;
1435 }
1436
1437 return true;
f1f41a6c 1438}
1439
de2b4872 1440
f1f41a6c 1441/* Ensure that this vector has exactly NELEMS slots available. This
1442 will not create additional headroom. Note this can cause the
1443 embedded vector to be reallocated. Returns true iff reallocation
1444 actually occurred. */
de2b4872 1445
d70aebca 1446template<typename T>
f1f41a6c 1447inline bool
d70aebca 1448vec<T, va_heap, vl_ptr>::reserve_exact (unsigned nelems MEM_STAT_DECL)
f1f41a6c 1449{
1450 return reserve (nelems, true PASS_MEM_STAT);
1451}
1452
1453
1454/* Create the internal vector and reserve NELEMS for it. This is
1455 exactly like vec::reserve, but the internal vector is
1456 unconditionally allocated from scratch. The old one, if it
1457 existed, is lost. */
1458
d70aebca 1459template<typename T>
f1f41a6c 1460inline void
d70aebca 1461vec<T, va_heap, vl_ptr>::create (unsigned nelems MEM_STAT_DECL)
f1f41a6c 1462{
fd3aba29 1463 m_vec = NULL;
f1f41a6c 1464 if (nelems > 0)
1465 reserve_exact (nelems PASS_MEM_STAT);
1466}
1467
1468
1469/* Free the memory occupied by the embedded vector. */
1470
d70aebca 1471template<typename T>
f1f41a6c 1472inline void
d70aebca 1473vec<T, va_heap, vl_ptr>::release (void)
f1f41a6c 1474{
d70aebca 1475 if (!m_vec)
1476 return;
f1f41a6c 1477
d70aebca 1478 if (using_auto_storage ())
1479 {
ec456ba8 1480 m_vec->m_vecpfx.m_num = 0;
d70aebca 1481 return;
1482 }
1483
1484 va_heap::release (m_vec);
1485}
f1f41a6c 1486
1487/* Copy the elements from SRC to the end of this vector as if by memcpy.
1488 SRC and this vector must be allocated with the same memory
1489 allocation mechanism. This vector is assumed to have sufficient
1490 headroom available. */
1491
d70aebca 1492template<typename T>
f1f41a6c 1493inline void
103be950 1494vec<T, va_heap, vl_ptr>::splice (const vec<T, va_heap, vl_ptr> &src)
f1f41a6c 1495{
fd3aba29 1496 if (src.m_vec)
1497 m_vec->splice (*(src.m_vec));
f1f41a6c 1498}
1499
1500
1501/* Copy the elements in SRC to the end of this vector as if by memcpy.
1502 SRC and this vector must be allocated with the same mechanism.
1503 If there is not enough headroom in this vector, it will be reallocated
1504 as needed. */
1505
d70aebca 1506template<typename T>
f1f41a6c 1507inline void
103be950 1508vec<T, va_heap, vl_ptr>::safe_splice (const vec<T, va_heap, vl_ptr> &src
d70aebca 1509 MEM_STAT_DECL)
f1f41a6c 1510{
9af5ce0c 1511 if (src.length ())
2b15d2ba 1512 {
9af5ce0c 1513 reserve_exact (src.length ());
f1f41a6c 1514 splice (src);
2b15d2ba 1515 }
f1f41a6c 1516}
1517
1518
1519/* Push OBJ (a new element) onto the end of the vector. There must be
1520 sufficient space in the vector. Return a pointer to the slot
1521 where OBJ was inserted. */
1522
d70aebca 1523template<typename T>
f1f41a6c 1524inline T *
d70aebca 1525vec<T, va_heap, vl_ptr>::quick_push (const T &obj)
f1f41a6c 1526{
fd3aba29 1527 return m_vec->quick_push (obj);
f1f41a6c 1528}
1529
1530
1531/* Push a new element OBJ onto the end of this vector. Reallocates
1532 the embedded vector, if needed. Return a pointer to the slot where
1533 OBJ was inserted. */
1534
d70aebca 1535template<typename T>
f1f41a6c 1536inline T *
d70aebca 1537vec<T, va_heap, vl_ptr>::safe_push (const T &obj MEM_STAT_DECL)
f1f41a6c 1538{
1539 reserve (1, false PASS_MEM_STAT);
1540 return quick_push (obj);
1541}
1542
de2b4872 1543
f1f41a6c 1544/* Pop and return the last element off the end of the vector. */
1545
d70aebca 1546template<typename T>
f1f41a6c 1547inline T &
d70aebca 1548vec<T, va_heap, vl_ptr>::pop (void)
f1f41a6c 1549{
fd3aba29 1550 return m_vec->pop ();
f1f41a6c 1551}
1552
1553
1554/* Set the length of the vector to LEN. The new length must be less
1555 than or equal to the current length. This is an O(1) operation. */
1556
d70aebca 1557template<typename T>
f1f41a6c 1558inline void
d70aebca 1559vec<T, va_heap, vl_ptr>::truncate (unsigned size)
f1f41a6c 1560{
fd3aba29 1561 if (m_vec)
1562 m_vec->truncate (size);
f1f41a6c 1563 else
1564 gcc_checking_assert (size == 0);
1565}
1566
1567
1568/* Grow the vector to a specific length. LEN must be as long or
1569 longer than the current length. The new elements are
1570 uninitialized. Reallocate the internal vector, if needed. */
1571
d70aebca 1572template<typename T>
f1f41a6c 1573inline void
d70aebca 1574vec<T, va_heap, vl_ptr>::safe_grow (unsigned len MEM_STAT_DECL)
f1f41a6c 1575{
1576 unsigned oldlen = length ();
1577 gcc_checking_assert (oldlen <= len);
1578 reserve_exact (len - oldlen PASS_MEM_STAT);
e59421db 1579 if (m_vec)
1580 m_vec->quick_grow (len);
1581 else
1582 gcc_checking_assert (len == 0);
f1f41a6c 1583}
1584
1585
1586/* Grow the embedded vector to a specific length. LEN must be as
1587 long or longer than the current length. The new elements are
1588 initialized to zero. Reallocate the internal vector, if needed. */
1589
d70aebca 1590template<typename T>
f1f41a6c 1591inline void
d70aebca 1592vec<T, va_heap, vl_ptr>::safe_grow_cleared (unsigned len MEM_STAT_DECL)
f1f41a6c 1593{
1594 unsigned oldlen = length ();
1595 safe_grow (len PASS_MEM_STAT);
9af5ce0c 1596 memset (&(address ()[oldlen]), 0, sizeof (T) * (len - oldlen));
f1f41a6c 1597}
1598
1599
1600/* Same as vec::safe_grow but without reallocation of the internal vector.
1601 If the vector cannot be extended, a runtime assertion will be triggered. */
1602
d70aebca 1603template<typename T>
f1f41a6c 1604inline void
d70aebca 1605vec<T, va_heap, vl_ptr>::quick_grow (unsigned len)
f1f41a6c 1606{
fd3aba29 1607 gcc_checking_assert (m_vec);
1608 m_vec->quick_grow (len);
f1f41a6c 1609}
1610
1611
1612/* Same as vec::quick_grow_cleared but without reallocation of the
1613 internal vector. If the vector cannot be extended, a runtime
1614 assertion will be triggered. */
1615
d70aebca 1616template<typename T>
f1f41a6c 1617inline void
d70aebca 1618vec<T, va_heap, vl_ptr>::quick_grow_cleared (unsigned len)
f1f41a6c 1619{
fd3aba29 1620 gcc_checking_assert (m_vec);
1621 m_vec->quick_grow_cleared (len);
f1f41a6c 1622}
1623
1624
1625/* Insert an element, OBJ, at the IXth position of this vector. There
1626 must be sufficient space. */
1627
d70aebca 1628template<typename T>
f1f41a6c 1629inline void
d70aebca 1630vec<T, va_heap, vl_ptr>::quick_insert (unsigned ix, const T &obj)
f1f41a6c 1631{
fd3aba29 1632 m_vec->quick_insert (ix, obj);
f1f41a6c 1633}
1634
1635
1636/* Insert an element, OBJ, at the IXth position of the vector.
1637 Reallocate the embedded vector, if necessary. */
1638
d70aebca 1639template<typename T>
f1f41a6c 1640inline void
d70aebca 1641vec<T, va_heap, vl_ptr>::safe_insert (unsigned ix, const T &obj MEM_STAT_DECL)
f1f41a6c 1642{
1643 reserve (1, false PASS_MEM_STAT);
1644 quick_insert (ix, obj);
1645}
1646
1647
1648/* Remove an element from the IXth position of this vector. Ordering of
1649 remaining elements is preserved. This is an O(N) operation due to
1650 a memmove. */
1651
d70aebca 1652template<typename T>
f1f41a6c 1653inline void
d70aebca 1654vec<T, va_heap, vl_ptr>::ordered_remove (unsigned ix)
f1f41a6c 1655{
fd3aba29 1656 m_vec->ordered_remove (ix);
f1f41a6c 1657}
1658
1659
1660/* Remove an element from the IXth position of this vector. Ordering
1661 of remaining elements is destroyed. This is an O(1) operation. */
1662
d70aebca 1663template<typename T>
f1f41a6c 1664inline void
d70aebca 1665vec<T, va_heap, vl_ptr>::unordered_remove (unsigned ix)
f1f41a6c 1666{
fd3aba29 1667 m_vec->unordered_remove (ix);
f1f41a6c 1668}
1669
1670
1671/* Remove LEN elements starting at the IXth. Ordering is retained.
1672 This is an O(N) operation due to memmove. */
1673
d70aebca 1674template<typename T>
f1f41a6c 1675inline void
d70aebca 1676vec<T, va_heap, vl_ptr>::block_remove (unsigned ix, unsigned len)
f1f41a6c 1677{
fd3aba29 1678 m_vec->block_remove (ix, len);
f1f41a6c 1679}
1680
1681
1682/* Sort the contents of this vector with qsort. CMP is the comparison
1683 function to pass to qsort. */
1684
d70aebca 1685template<typename T>
f1f41a6c 1686inline void
d70aebca 1687vec<T, va_heap, vl_ptr>::qsort (int (*cmp) (const void *, const void *))
f1f41a6c 1688{
fd3aba29 1689 if (m_vec)
1690 m_vec->qsort (cmp);
f1f41a6c 1691}
1692
1693
3e48928c 1694/* Search the contents of the sorted vector with a binary search.
1695 CMP is the comparison function to pass to bsearch. */
1696
1697template<typename T>
1698inline T *
1699vec<T, va_heap, vl_ptr>::bsearch (const void *key,
1700 int (*cmp) (const void *, const void *))
1701{
1702 if (m_vec)
1703 return m_vec->bsearch (key, cmp);
1704 return NULL;
1705}
1706
1707
f1f41a6c 1708/* Find and return the first position in which OBJ could be inserted
1709 without changing the ordering of this vector. LESSTHAN is a
1710 function that returns true if the first argument is strictly less
1711 than the second. */
1712
d70aebca 1713template<typename T>
f1f41a6c 1714inline unsigned
d70aebca 1715vec<T, va_heap, vl_ptr>::lower_bound (T obj,
1716 bool (*lessthan)(const T &, const T &))
aad734b2 1717 const
f1f41a6c 1718{
fd3aba29 1719 return m_vec ? m_vec->lower_bound (obj, lessthan) : 0;
f7f05a07 1720}
1721
d70aebca 1722template<typename T>
1723inline bool
1724vec<T, va_heap, vl_ptr>::using_auto_storage () const
1725{
ec456ba8 1726 return m_vec->m_vecpfx.m_using_auto_storage;
d70aebca 1727}
1728
cac0c158 1729#if (GCC_VERSION >= 3000)
fd3aba29 1730# pragma GCC poison m_vec m_vecpfx m_vecdata
cac0c158 1731#endif
1732
f1f41a6c 1733#endif // GCC_VEC_H