VEC can be NULL, to create a new vector. */
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 >=
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;
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. */
+
+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);
+}
+
+/* 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. */
+
+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;
+
+ if (pfx && pfx->alloc >= alloc)
+ abort ();
+
+ vec = xrealloc (vec, vec_offset + alloc * elt_size);
+ ((struct vec_prefix *)vec)->alloc = alloc;
+ if (!pfx)
+ ((struct vec_prefix *)vec)->num = 0;
+
+ 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. */
The 'lower_bound' function will determine where to place an item in the
array using insert that will maintain sorted order.
+ Both garbage collected and explicitly managed vector types are
+ creatable. The allocation mechanism is specified when the type is
+ defined, and is therefore part of the type.
+
If you need to directly manipulate a vector, then the 'address'
accessor will return the address of the start of the vector. Also
the 'space' predicate will tell you whether there is spare capacity
in the vector. You will not normally need to use these two functions.
- Vector types are defined using a DEF_VEC_{O,P}(TYPEDEF) macro, and
- variables of vector type are declared using a VEC(TYPEDEF)
- macro. The characters O and P indicate whether TYPEDEF is a pointer
- (P) or object (O) type.
+ Vector types are defined using a DEF_VEC_{GC,MALLOC}_{O,P}(TYPEDEF)
+ macro, and variables of vector type are declared using a
+ VEC(TYPEDEF) macro. The tags GC and MALLOC specify the allocation
+ method -- garbage collected or explicit malloc/free calls. The
+ characters O and P indicate whether TYPEDEF is a pointer (P) or
+ object (O) type.
An example of their use would be,
- DEF_VEC_P(tree); // define a vector of tree pointers. This must
+ DEF_VEC_GC_P(tree); // define a gc'd vector of tree pointers. This must
// appear at file scope.
struct my_struct {
#define VEC_alloc(TDEF,A) (VEC_OP(TDEF,alloc)(A MEM_STAT_INFO))
+/* Free a vector.
+ void VEC_T_alloc(VEC(T) *&);
+
+ Free a vector and set it to NULL. */
+
+#define VEC_free(TDEF,V) (VEC_OP(TDEF,free)(&V))
+
/* Use these to determine the required size and initialization of a
vector embedded within another structure (as the final member).
#if !IN_GENGTYPE
/* Reallocate an array of elements with prefix. */
-extern void *vec_p_reserve (void *, int MEM_STAT_DECL);
-extern void *vec_o_reserve (void *, int, size_t, size_t MEM_STAT_DECL);
+extern void *vec_gc_p_reserve (void *, int MEM_STAT_DECL);
+extern void *vec_gc_o_reserve (void *, int, size_t, size_t MEM_STAT_DECL);
+extern void vec_gc_free (void *);
+extern void *vec_heap_p_reserve (void *, int MEM_STAT_DECL);
+extern void *vec_heap_o_reserve (void *, int, size_t, size_t MEM_STAT_DECL);
+extern void vec_heap_free (void *);
#if ENABLE_CHECKING
#define VEC_CHECK_INFO ,__FILE__,__LINE__,__FUNCTION__
/* Vector of pointer to object. */
#if IN_GENGTYPE
-{"DEF_VEC_P", VEC_STRINGIFY (VEC_TDEF (#)) ";", NULL},
+{"DEF_VEC_GC_P", VEC_STRINGIFY (VEC_TDEF (#)) ";", NULL},
+{"DEF_VEC_MALLOC_P", "", NULL},
#else
+#define DEF_VEC_GC_P(TDEF) DEF_VEC_P(TDEF,gc)
+#define DEF_VEC_MALLOC_P(TDEF) DEF_VEC_P(TDEF,heap)
-#define DEF_VEC_P(TDEF) \
+#define DEF_VEC_P(TDEF,a) \
VEC_TDEF (TDEF); \
\
static inline unsigned VEC_OP (TDEF,length) \
static inline VEC (TDEF) *VEC_OP (TDEF,alloc) \
(int alloc_ MEM_STAT_DECL) \
{ \
- return (VEC (TDEF) *) vec_p_reserve (NULL, alloc_ - !alloc_ PASS_MEM_STAT);\
+ return (VEC (TDEF) *) vec_##a##_p_reserve (NULL, alloc_ - !alloc_ PASS_MEM_STAT);\
+} \
+ \
+static inline void VEC_OP (TDEF,free) \
+ (VEC (TDEF) **vec_) \
+{ \
+ vec_##a##_free (*vec_); \
+ *vec_ = NULL; \
} \
\
static inline size_t VEC_OP (TDEF,embedded_size) \
int extend = VEC_OP (TDEF,space) (*vec_, alloc_); \
\
if (extend) \
- *vec_ = (VEC (TDEF) *) vec_p_reserve (*vec_, alloc_ PASS_MEM_STAT); \
+ *vec_ = (VEC (TDEF) *) vec_##a##_p_reserve (*vec_, alloc_ PASS_MEM_STAT); \
\
return extend; \
} \
/* Vector of object. */
#if IN_GENGTYPE
-{"DEF_VEC_O", VEC_STRINGIFY (VEC_TDEF (#)) ";", NULL},
+{"DEF_VEC_GC_O", VEC_STRINGIFY (VEC_TDEF (#)) ";", NULL},
+{"DEF_VEC_MALLOC_O", "", NULL},
#else
-#define DEF_VEC_O(TDEF) \
+#define DEF_VEC_GC_O(TDEF) DEF_VEC_O(TDEF,gc)
+#define DEF_VEC_MALLOC_O(TDEF) DEF_VEC_O(TDEF,heap)
+
+#define DEF_VEC_O(TDEF,a) \
VEC_TDEF (TDEF); \
\
static inline unsigned VEC_OP (TDEF,length) \
static inline VEC (TDEF) *VEC_OP (TDEF,alloc) \
(int alloc_ MEM_STAT_DECL) \
{ \
- return (VEC (TDEF) *) vec_o_reserve (NULL, alloc_ - !alloc_, \
+ return (VEC (TDEF) *) vec_##a##_o_reserve (NULL, alloc_ - !alloc_, \
offsetof (VEC(TDEF),vec), sizeof (TDEF)\
PASS_MEM_STAT); \
} \
\
+static inline void VEC_OP (TDEF,free) \
+ (VEC (TDEF) **vec_) \
+{ \
+ vec_##a##_free (*vec_); \
+ *vec_ = NULL; \
+} \
+ \
static inline size_t VEC_OP (TDEF,embedded_size) \
(int alloc_) \
{ \
int extend = VEC_OP (TDEF,space) (*vec_, alloc_); \
\
if (extend) \
- *vec_ = (VEC (TDEF) *) vec_o_reserve (*vec_, alloc_, \
+ *vec_ = (VEC (TDEF) *) vec_##a##_o_reserve (*vec_, alloc_, \
offsetof (VEC(TDEF),vec), sizeof (TDEF) \
PASS_MEM_STAT); \
\