summaryrefslogtreecommitdiff
path: root/gcc/vec.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/vec.c')
-rw-r--r--gcc/vec.c111
1 files changed, 60 insertions, 51 deletions
diff --git a/gcc/vec.c b/gcc/vec.c
index c638ead9bf5..67643b5abd2 100644
--- a/gcc/vec.c
+++ b/gcc/vec.c
@@ -34,9 +34,54 @@ struct vec_prefix
void *vec[1];
};
-/* Ensure there are at least RESERVE free slots in VEC, if RESERVE >=
- 0. If RESERVE < 0 increase the current allocation exponentially.
- VEC can be NULL, to create a new vector. */
+/* Calculate the new ALLOC value, making sure that abs(RESERVE) slots
+ are free. If RESERVE < 0 grow exactly, otherwise grow
+ exponentially. */
+
+static inline unsigned
+calculate_allocation (const struct vec_prefix *pfx, int reserve)
+{
+ unsigned alloc = 0;
+ unsigned num = 0;
+
+ if (pfx)
+ {
+ alloc = pfx->alloc;
+ num = pfx->num;
+ }
+ else if (!reserve)
+ /* If there's no prefix, and we've not requested anything, then we
+ will create a NULL vector. */
+ return 0;
+
+ /* We must have run out of room. */
+ gcc_assert (alloc - num < (unsigned)(reserve < 0 ? -reserve : reserve));
+
+ if (reserve < 0)
+ /* Exact size. */
+ alloc = num + -reserve;
+ else
+ {
+ /* Exponential growth. */
+ if (!alloc)
+ alloc = 4;
+ else if (alloc < 16)
+ /* Double when small. */
+ alloc = alloc * 2;
+ else
+ /* Grow slower when large. */
+ alloc = (alloc * 3 / 2);
+
+ /* If this is still too small, set it to the right size. */
+ if (alloc < num + reserve)
+ alloc = num + reserve;
+ }
+ 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. */
void *
vec_gc_p_reserve (void *vec, int reserve MEM_STAT_DECL)
@@ -46,27 +91,19 @@ vec_gc_p_reserve (void *vec, int reserve MEM_STAT_DECL)
PASS_MEM_STAT);
}
-/* Ensure there are at least RESERVE free slots in VEC, if RESERVE >=
- 0. If RESERVE < 0, increase the current allocation exponentially.
- VEC can be NULL, in which case a new vector is created. The
- vector's trailing array is at VEC_OFFSET offset and consists of
- ELT_SIZE sized elements. */
+/* 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)
{
struct vec_prefix *pfx = vec;
- unsigned alloc = pfx ? pfx->num : 0;
-
- if (reserve >= 0)
- alloc += reserve;
- else if (alloc)
- alloc *= 2;
- else
- alloc = 4;
-
- gcc_assert (!pfx || pfx->alloc < alloc);
+ unsigned alloc = alloc = calculate_allocation (pfx, reserve);
+
+ if (!alloc)
+ return NULL;
vec = ggc_realloc_stat (vec, vec_offset + alloc * elt_size PASS_MEM_STAT);
((struct vec_prefix *)vec)->alloc = alloc;
@@ -76,17 +113,7 @@ vec_gc_o_reserve (void *vec, int reserve, size_t vec_offset, size_t elt_size
return vec;
}
-/* Explicitly release a vector. */
-
-void
-vec_gc_free (void *vec)
-{
- ggc_free (vec);
-}
-
-/* Ensure there are at least RESERVE free slots in VEC, if RESERVE >=
- 0. If RESERVE < 0 increase the current allocation exponentially.
- VEC can be NULL, to create a new vector. */
+/* As for vec_gc_p_reserve, but for heap allocated vectors. */
void *
vec_heap_p_reserve (void *vec, int reserve MEM_STAT_DECL)
@@ -96,27 +123,17 @@ vec_heap_p_reserve (void *vec, int reserve MEM_STAT_DECL)
PASS_MEM_STAT);
}
-/* Ensure there are at least RESERVE free slots in VEC, if RESERVE >=
- 0. If RESERVE < 0, increase the current allocation exponentially.
- VEC can be NULL, in which case a new vector is created. The
- vector's trailing array is at VEC_OFFSET offset and consists of
- ELT_SIZE sized elements. */
+/* 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)
{
struct vec_prefix *pfx = vec;
- unsigned alloc = pfx ? pfx->num : 0;
-
- if (reserve >= 0)
- alloc += reserve;
- else if (alloc)
- alloc *= 2;
- else
- alloc = 4;
+ unsigned alloc = calculate_allocation (pfx, reserve);
- gcc_assert (!pfx || pfx->alloc < alloc);
+ if (!alloc)
+ return NULL;
vec = xrealloc (vec, vec_offset + alloc * elt_size);
((struct vec_prefix *)vec)->alloc = alloc;
@@ -126,14 +143,6 @@ vec_heap_o_reserve (void *vec, int reserve, size_t vec_offset, size_t elt_size
return vec;
}
-/* Explicitly release a vector. */
-
-void
-vec_heap_free (void *vec)
-{
- free (vec);
-}
-
#if ENABLE_CHECKING
/* Issue a vector domain error, and then fall over. */