/* Vector API for GNU compiler.
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
Contributed by Nathan Sidwell <nathan@codesourcery.com>
This file is part of GCC.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
#include "config.h"
#include "system.h"
#include "ggc.h"
#include "vec.h"
-#include "errors.h"
#include "coretypes.h"
#include "tree.h"
+#include "toplev.h"
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_p_reserve (void *vec, int reserve MEM_STAT_DECL)
+vec_gc_p_reserve (void *vec, int reserve MEM_STAT_DECL)
{
- return vec_o_reserve (vec, reserve,
- offsetof (struct vec_prefix, vec), sizeof (void *)
- PASS_MEM_STAT);
+ return vec_gc_o_reserve (vec, reserve,
+ offsetof (struct vec_prefix, vec), sizeof (void *)
+ 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 consistes 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_o_reserve (void *vec, int reserve, size_t vec_offset, size_t elt_size
- MEM_STAT_DECL)
+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;
+ 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;
+ if (!pfx)
+ ((struct vec_prefix *)vec)->num = 0;
+
+ return vec;
+}
- if (reserve >= 0)
- alloc += reserve;
- else if (alloc)
- alloc *= 2;
- else
- alloc = 4;
+/* 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 (vec, reserve,
+ offsetof (struct vec_prefix, vec), sizeof (void *)
+ PASS_MEM_STAT);
+}
+
+/* As for vec_gc_o_reserve, but for heap allocated vectors. */
- if (pfx && pfx->alloc >= alloc)
- abort ();
+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 = calculate_allocation (pfx, reserve);
+
+ if (!alloc)
+ return NULL;
- vec = ggc_realloc_stat (vec, vec_offset + alloc * elt_size PASS_MEM_STAT);
+ vec = xrealloc (vec, vec_offset + alloc * elt_size);
((struct vec_prefix *)vec)->alloc = alloc;
if (!pfx)
((struct vec_prefix *)vec)->num = 0;