void *vec[1];
};
-/* Calculate the new ALLOC value, making sure that abs(RESERVE) slots
- are free. If RESERVE < 0 grow exactly, otherwise grow
- exponentially. */
+/* Calculate the new ALLOC value, making sure that RESERVE slots are
+ free. If EXACT grow exactly, otherwise grow exponentially. */
static inline unsigned
-calculate_allocation (const struct vec_prefix *pfx, int reserve)
+calculate_allocation (const struct vec_prefix *pfx, int reserve, bool exact)
{
unsigned alloc = 0;
unsigned num = 0;
+ gcc_assert (reserve >= 0);
+
if (pfx)
{
alloc = pfx->alloc;
return 0;
/* We must have run out of room. */
- gcc_assert (alloc - num < (unsigned)(reserve < 0 ? -reserve : reserve));
+ gcc_assert (alloc - num < (unsigned) reserve);
- if (reserve < 0)
+ if (exact)
/* Exact size. */
- alloc = num + -reserve;
+ alloc = num + reserve;
else
{
/* Exponential growth. */
return alloc;
}
-/* Ensure there are at least abs(RESERVE) free slots in VEC. If
- RESERVE < 0 grow exactly, else grow exponentially. As a special
- case, if VEC is NULL, and RESERVE is 0, no vector will be created. */
+/* Ensure there are at least RESERVE free slots in VEC. If EXACT grow
+ exactly, else grow exponentially. As a special case, if VEC is
+ NULL and RESERVE is 0, no vector will be created. The vector's
+ trailing array is at VEC_OFFSET offset and consists of ELT_SIZE
+ sized elements. */
-void *
-vec_gc_p_reserve (void *vec, int reserve MEM_STAT_DECL)
-{
- return vec_gc_o_reserve (vec, reserve,
- offsetof (struct vec_prefix, vec), sizeof (void *)
- PASS_MEM_STAT);
-}
-
-/* As vec_gc_p_reserve, but for object vectors. The vector's trailing
- array is at VEC_OFFSET offset and consists of ELT_SIZE sized
- elements. */
-
-void *
-vec_gc_o_reserve (void *vec, int reserve, size_t vec_offset, size_t elt_size
- MEM_STAT_DECL)
+static void *
+vec_gc_o_reserve_1 (void *vec, int reserve, size_t vec_offset, size_t elt_size,
+ bool exact MEM_STAT_DECL)
{
struct vec_prefix *pfx = vec;
- unsigned alloc = alloc = calculate_allocation (pfx, reserve);
+ unsigned alloc = alloc = calculate_allocation (pfx, reserve, exact);
if (!alloc)
return NULL;
return vec;
}
-/* As for vec_gc_p_reserve, but for heap allocated vectors. */
+/* Ensure there are at least RESERVE free slots in VEC, growing
+ exponentially. If RESERVE < 0 grow exactly, else grow
+ exponentially. As a special case, if VEC is NULL, and RESERVE is
+ 0, no vector will be created. */
void *
-vec_heap_p_reserve (void *vec, int reserve MEM_STAT_DECL)
+vec_gc_p_reserve (void *vec, int reserve MEM_STAT_DECL)
{
- return vec_heap_o_reserve (vec, reserve,
- offsetof (struct vec_prefix, vec), sizeof (void *)
+ return vec_gc_o_reserve_1 (vec, reserve,
+ offsetof (struct vec_prefix, vec),
+ sizeof (void *), false
PASS_MEM_STAT);
}
-/* As for vec_gc_o_reserve, but for heap allocated vectors. */
+/* Ensure there are at least RESERVE free slots in VEC, growing
+ exactly. If RESERVE < 0 grow exactly, else grow exponentially. As
+ a special case, if VEC is NULL, and RESERVE is 0, no vector will be
+ created. */
void *
-vec_heap_o_reserve (void *vec, int reserve, size_t vec_offset, size_t elt_size
- MEM_STAT_DECL)
+vec_gc_p_reserve_exact (void *vec, int reserve MEM_STAT_DECL)
+{
+ return vec_gc_o_reserve_1 (vec, reserve,
+ offsetof (struct vec_prefix, vec),
+ sizeof (void *), true
+ PASS_MEM_STAT);
+}
+
+/* As for vec_gc_p_reserve, but for object vectors. The vector's
+ trailing array is at VEC_OFFSET offset and consists of ELT_SIZE
+ sized elements. */
+
+void *
+vec_gc_o_reserve (void *vec, int reserve, size_t vec_offset, size_t elt_size
+ MEM_STAT_DECL)
+{
+ return vec_gc_o_reserve_1 (vec, reserve, vec_offset, elt_size, false
+ PASS_MEM_STAT);
+}
+
+/* As for vec_gc_p_reserve_exact, but for object vectors. The
+ vector's trailing array is at VEC_OFFSET offset and consists of
+ ELT_SIZE sized elements. */
+
+void *
+vec_gc_o_reserve_exact (void *vec, int reserve, size_t vec_offset,
+ size_t elt_size MEM_STAT_DECL)
+{
+ return vec_gc_o_reserve_1 (vec, reserve, vec_offset, elt_size, true
+ PASS_MEM_STAT);
+}
+
+/* As for vec_gc_o_reserve_1, but for heap allocated vectors. */
+
+static void *
+vec_heap_o_reserve_1 (void *vec, int reserve, size_t vec_offset,
+ size_t elt_size, bool exact MEM_STAT_DECL)
{
struct vec_prefix *pfx = vec;
- unsigned alloc = calculate_allocation (pfx, reserve);
+ unsigned alloc = calculate_allocation (pfx, reserve, exact);
if (!alloc)
return NULL;
return vec;
}
+/* As for vec_gc_p_reserve, but for heap allocated vectors. */
+
+void *
+vec_heap_p_reserve (void *vec, int reserve MEM_STAT_DECL)
+{
+ return vec_heap_o_reserve_1 (vec, reserve,
+ offsetof (struct vec_prefix, vec),
+ sizeof (void *), false
+ PASS_MEM_STAT);
+}
+
+/* As for vec_gc_p_reserve_exact, but for heap allocated vectors. */
+
+void *
+vec_heap_p_reserve_exact (void *vec, int reserve MEM_STAT_DECL)
+{
+ return vec_heap_o_reserve_1 (vec, reserve,
+ offsetof (struct vec_prefix, vec),
+ sizeof (void *), true
+ PASS_MEM_STAT);
+}
+
+/* As for vec_gc_o_reserve, but for heap allocated vectors. */
+
+void *
+vec_heap_o_reserve (void *vec, int reserve, size_t vec_offset, size_t elt_size
+ MEM_STAT_DECL)
+{
+ return vec_heap_o_reserve_1 (vec, reserve, vec_offset, elt_size, false
+ PASS_MEM_STAT);
+}
+
+/* As for vec_gc_o_reserve_exact, but for heap allocated vectors. */
+
+void *
+vec_heap_o_reserve_exact (void *vec, int reserve, size_t vec_offset,
+ size_t elt_size MEM_STAT_DECL)
+{
+ return vec_heap_o_reserve_1 (vec, reserve, vec_offset, elt_size, true
+ PASS_MEM_STAT);
+}
+
#if ENABLE_CHECKING
/* Issue a vector domain error, and then fall over. */
least as many elements as you ask for, it will exponentially
increase if there are too few spare slots. If you want reserve a
specific number of slots, but do not want the exponential increase
- (for instance, you know this is the last allocation), use a
- negative number for reservation. You can also create a vector of a
+ (for instance, you know this is the last allocation), use the
+ reserve_exact operation. You can also create a vector of a
specific size from the get go.
You should prefer the push and pop operations, as they append and
/* Reserve space.
int VEC_T_A_reserve(VEC(T,A) *&v, int reserve);
- Ensure that V has at least abs(RESERVE) slots available. The
- signedness of RESERVE determines the reallocation behavior. A
- negative value will not create additional headroom beyond that
- requested. A positive value will create additional headroom. Note
- this can cause V to be reallocated. Returns nonzero iff
- reallocation actually occurred. */
+ Ensure that V has at least RESERVE slots available. This will
+ create additional headroom. Note this can cause V to be
+ reallocated. Returns nonzero iff reallocation actually
+ occurred. */
#define VEC_reserve(T,A,V,R) \
(VEC_OP(T,A,reserve)(&(V),R VEC_CHECK_INFO MEM_STAT_INFO))
+/* Reserve space exactly.
+ int VEC_T_A_reserve_exact(VEC(T,A) *&v, int reserve);
+
+ Ensure that V has at least RESERVE slots available. This will not
+ create additional headroom. Note this can cause V to be
+ reallocated. Returns nonzero iff reallocation actually
+ occurred. */
+
+#define VEC_reserve_exact(T,A,V,R) \
+ (VEC_OP(T,A,reserve_exact)(&(V),R VEC_CHECK_INFO MEM_STAT_INFO))
+
/* Push object with no reallocation
T *VEC_T_quick_push (VEC(T) *v, T obj); // Integer
T *VEC_T_quick_push (VEC(T) *v, T obj); // Pointer
#if !IN_GENGTYPE
/* Reallocate an array of elements with prefix. */
extern void *vec_gc_p_reserve (void *, int MEM_STAT_DECL);
+extern void *vec_gc_p_reserve_exact (void *, int MEM_STAT_DECL);
extern void *vec_gc_o_reserve (void *, int, size_t, size_t MEM_STAT_DECL);
+extern void *vec_gc_o_reserve_exact (void *, int, size_t, size_t
+ MEM_STAT_DECL);
extern void ggc_free (void *);
#define vec_gc_free(V) ggc_free (V)
extern void *vec_heap_p_reserve (void *, int MEM_STAT_DECL);
+extern void *vec_heap_p_reserve_exact (void *, int MEM_STAT_DECL);
extern void *vec_heap_o_reserve (void *, int, size_t, size_t MEM_STAT_DECL);
+extern void *vec_heap_o_reserve_exact (void *, int, size_t, size_t
+ MEM_STAT_DECL);
#define vec_heap_free(V) free (V)
#if ENABLE_CHECKING
static inline VEC(T,A) *VEC_OP (T,A,alloc) \
(int alloc_ MEM_STAT_DECL) \
{ \
- /* We must request exact size allocation, hence the negation. */ \
- return (VEC(T,A) *) vec_##A##_p_reserve (NULL, -alloc_ PASS_MEM_STAT); \
+ return (VEC(T,A) *) vec_##A##_p_reserve_exact (NULL, alloc_ \
+ PASS_MEM_STAT); \
} \
\
static inline void VEC_OP (T,A,free) \
\
if (len_) \
{ \
- /* We must request exact size allocation, hence the negation. */ \
- new_vec_ = (VEC (T,A) *)(vec_##A##_p_reserve \
- (NULL, -len_ PASS_MEM_STAT)); \
+ new_vec_ = (VEC (T,A) *)(vec_##A##_p_reserve_exact \
+ (NULL, len_ PASS_MEM_STAT)); \
\
new_vec_->base.num = len_; \
memcpy (new_vec_->base.vec, vec_->vec, sizeof (T) * len_); \
static inline int VEC_OP (T,A,reserve) \
(VEC(T,A) **vec_, int alloc_ VEC_CHECK_DECL MEM_STAT_DECL) \
{ \
- int extend = !VEC_OP (T,base,space) (VEC_BASE(*vec_), \
- alloc_ < 0 ? -alloc_ : alloc_ \
+ int extend = !VEC_OP (T,base,space) (VEC_BASE(*vec_), alloc_ \
VEC_CHECK_PASS); \
\
if (extend) \
return extend; \
} \
\
+static inline int VEC_OP (T,A,reserve_exact) \
+ (VEC(T,A) **vec_, int alloc_ VEC_CHECK_DECL MEM_STAT_DECL) \
+{ \
+ int extend = !VEC_OP (T,base,space) (VEC_BASE(*vec_), alloc_ \
+ VEC_CHECK_PASS); \
+ \
+ if (extend) \
+ *vec_ = (VEC(T,A) *) vec_##A##_p_reserve_exact (*vec_, alloc_ \
+ PASS_MEM_STAT); \
+ \
+ return extend; \
+} \
+ \
static inline void VEC_OP (T,A,safe_grow) \
(VEC(T,A) **vec_, int size_ VEC_CHECK_DECL MEM_STAT_DECL) \
{ \
VEC_ASSERT (size_ >= 0 \
&& VEC_OP(T,base,length) VEC_BASE(*vec_) <= (unsigned)size_, \
"grow", T, A); \
- VEC_OP (T,A,reserve) (vec_, (int)(*vec_ ? VEC_BASE(*vec_)->num : 0) - size_ \
- VEC_CHECK_PASS PASS_MEM_STAT); \
+ VEC_OP (T,A,reserve_exact) (vec_, \
+ size_ - (int)(*vec_ ? VEC_BASE(*vec_)->num : 0) \
+ VEC_CHECK_PASS PASS_MEM_STAT); \
VEC_BASE (*vec_)->num = size_; \
} \
\
static inline VEC(T,A) *VEC_OP (T,A,alloc) \
(int alloc_ MEM_STAT_DECL) \
{ \
- /* We must request exact size allocation, hence the negation. */ \
- return (VEC(T,A) *) vec_##A##_o_reserve (NULL, -alloc_, \
- offsetof (VEC(T,A),base.vec), \
- sizeof (T) \
- PASS_MEM_STAT); \
+ return (VEC(T,A) *) vec_##A##_o_reserve_exact (NULL, alloc_, \
+ offsetof (VEC(T,A),base.vec), \
+ sizeof (T) \
+ PASS_MEM_STAT); \
} \
\
static inline VEC(T,A) *VEC_OP (T,A,copy) (VEC(T,base) *vec_ MEM_STAT_DECL) \
\
if (len_) \
{ \
- /* We must request exact size allocation, hence the negation. */ \
- new_vec_ = (VEC (T,A) *)(vec_##A##_o_reserve \
- (NULL, -len_, \
+ new_vec_ = (VEC (T,A) *)(vec_##A##_o_reserve_exact \
+ (NULL, len_, \
offsetof (VEC(T,A),base.vec), sizeof (T) \
PASS_MEM_STAT)); \
\
static inline int VEC_OP (T,A,reserve) \
(VEC(T,A) **vec_, int alloc_ VEC_CHECK_DECL MEM_STAT_DECL) \
{ \
- int extend = !VEC_OP (T,base,space) (VEC_BASE(*vec_), \
- alloc_ < 0 ? -alloc_ : alloc_ \
+ int extend = !VEC_OP (T,base,space) (VEC_BASE(*vec_), alloc_ \
VEC_CHECK_PASS); \
\
if (extend) \
return extend; \
} \
\
+static inline int VEC_OP (T,A,reserve_exact) \
+ (VEC(T,A) **vec_, int alloc_ VEC_CHECK_DECL MEM_STAT_DECL) \
+{ \
+ int extend = !VEC_OP (T,base,space) (VEC_BASE(*vec_), alloc_ \
+ VEC_CHECK_PASS); \
+ \
+ if (extend) \
+ *vec_ = (VEC(T,A) *) vec_##A##_o_reserve_exact \
+ (*vec_, alloc_, \
+ offsetof (VEC(T,A),base.vec), \
+ sizeof (T) PASS_MEM_STAT); \
+ \
+ return extend; \
+} \
+ \
static inline void VEC_OP (T,A,safe_grow) \
(VEC(T,A) **vec_, int size_ VEC_CHECK_DECL MEM_STAT_DECL) \
{ \
VEC_ASSERT (size_ >= 0 \
&& VEC_OP(T,base,length) VEC_BASE(*vec_) <= (unsigned)size_, \
"grow", T, A); \
- VEC_OP (T,A,reserve) (vec_, (int)(*vec_ ? VEC_BASE(*vec_)->num : 0) - size_ \
- VEC_CHECK_PASS PASS_MEM_STAT); \
+ VEC_OP (T,A,reserve_exact) (vec_, \
+ size_ - (int)(*vec_ ? VEC_BASE(*vec_)->num : 0) \
+ VEC_CHECK_PASS PASS_MEM_STAT); \
VEC_BASE (*vec_)->num = size_; \
} \
\
static inline VEC(T,A) *VEC_OP (T,A,alloc) \
(int alloc_ MEM_STAT_DECL) \
{ \
- /* We must request exact size allocation, hence the negation. */ \
- return (VEC(T,A) *) vec_##A##_o_reserve (NULL, -alloc_, \
- offsetof (VEC(T,A),base.vec), \
- sizeof (T) \
- PASS_MEM_STAT); \
+ return (VEC(T,A) *) vec_##A##_o_reserve_exact \
+ (NULL, alloc_, offsetof (VEC(T,A),base.vec), \
+ sizeof (T) PASS_MEM_STAT); \
} \
\
static inline VEC(T,A) *VEC_OP (T,A,copy) (VEC(T,base) *vec_ MEM_STAT_DECL) \
\
if (len_) \
{ \
- /* We must request exact size allocation, hence the negation. */ \
- new_vec_ = (VEC (T,A) *)(vec_##A##_o_reserve \
- (NULL, -len_, \
+ new_vec_ = (VEC (T,A) *)(vec_##A##_o_reserve_exact \
+ (NULL, len_, \
offsetof (VEC(T,A),base.vec), sizeof (T) \
PASS_MEM_STAT)); \
\
static inline int VEC_OP (T,A,reserve) \
(VEC(T,A) **vec_, int alloc_ VEC_CHECK_DECL MEM_STAT_DECL) \
{ \
- int extend = !VEC_OP (T,base,space) (VEC_BASE(*vec_), \
- alloc_ < 0 ? -alloc_ : alloc_ \
+ int extend = !VEC_OP (T,base,space) (VEC_BASE(*vec_), alloc_ \
VEC_CHECK_PASS); \
\
if (extend) \
return extend; \
} \
\
+static inline int VEC_OP (T,A,reserve_exact) \
+ (VEC(T,A) **vec_, int alloc_ VEC_CHECK_DECL MEM_STAT_DECL) \
+{ \
+ int extend = !VEC_OP (T,base,space) (VEC_BASE(*vec_), alloc_ \
+ VEC_CHECK_PASS); \
+ \
+ if (extend) \
+ *vec_ = (VEC(T,A) *) vec_##A##_o_reserve_exact \
+ (*vec_, alloc_, offsetof (VEC(T,A),base.vec), \
+ sizeof (T) PASS_MEM_STAT); \
+ \
+ return extend; \
+} \
+ \
static inline void VEC_OP (T,A,safe_grow) \
(VEC(T,A) **vec_, int size_ VEC_CHECK_DECL MEM_STAT_DECL) \
{ \
VEC_ASSERT (size_ >= 0 \
&& VEC_OP(T,base,length) VEC_BASE(*vec_) <= (unsigned)size_, \
"grow", T, A); \
- VEC_OP (T,A,reserve) (vec_, (int)(*vec_ ? VEC_BASE(*vec_)->num : 0) - size_ \
- VEC_CHECK_PASS PASS_MEM_STAT); \
+ VEC_OP (T,A,reserve_exact) (vec_, \
+ size_ - (int)(*vec_ ? VEC_BASE(*vec_)->num : 0) \
+ VEC_CHECK_PASS PASS_MEM_STAT); \
VEC_BASE (*vec_)->num = size_; \
} \
\