3 * Copyright 2016 Xamarin, Inc.
5 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
8 // Growable array implementation used by sgen-new-bridge and sgen-tarjan-bridge.
12 int capacity
; /* if negative, data points to another DynArray's data */
18 // IntArray supports an optimization (in sgen-new-bridge.c): If capacity is less than 0 it is a "copy" and does not own its buffer.
23 // PtrArray supports an optimization: If size is equal to 1 it is a "singleton" and data points to the single held item, not to a buffer.
33 dyn_array_init (DynArray
*da
)
41 dyn_array_uninit (DynArray
*da
, int elem_size
)
43 if (da
->capacity
< 0) {
48 if (da
->capacity
== 0)
51 sgen_free_internal_dynamic (da
->data
, elem_size
* da
->capacity
, INTERNAL_MEM_BRIDGE_DATA
);
56 dyn_array_empty (DynArray
*da
)
65 dyn_array_ensure_capacity_internal (DynArray
*da
, int capacity
, int elem_size
)
67 if (da
->capacity
<= 0)
69 while (capacity
> da
->capacity
)
72 return (char *)sgen_alloc_internal_dynamic (elem_size
* da
->capacity
, INTERNAL_MEM_BRIDGE_DATA
, TRUE
);
76 dyn_array_ensure_capacity (DynArray
*da
, int capacity
, int elem_size
)
78 int old_capacity
= da
->capacity
;
81 g_assert (capacity
> 0);
83 if (capacity
<= old_capacity
)
86 new_data
= dyn_array_ensure_capacity_internal (da
, capacity
, elem_size
);
87 memcpy (new_data
, da
->data
, elem_size
* da
->size
);
89 sgen_free_internal_dynamic (da
->data
, elem_size
* old_capacity
, INTERNAL_MEM_BRIDGE_DATA
);
94 dyn_array_is_copy (DynArray
*da
)
96 return da
->capacity
< 0;
100 dyn_array_ensure_independent (DynArray
*da
, int elem_size
)
102 if (!dyn_array_is_copy (da
))
104 dyn_array_ensure_capacity (da
, da
->size
, elem_size
);
105 g_assert (da
->capacity
> 0);
109 dyn_array_add (DynArray
*da
, int elem_size
)
113 dyn_array_ensure_capacity (da
, da
->size
+ 1, elem_size
);
115 p
= da
->data
+ da
->size
* elem_size
;
121 dyn_array_copy (DynArray
*dst
, DynArray
*src
, int elem_size
)
123 dyn_array_uninit (dst
, elem_size
);
128 dst
->size
= src
->size
;
130 dst
->data
= src
->data
;
135 dyn_array_int_init (DynIntArray
*da
)
137 dyn_array_init (&da
->array
);
141 dyn_array_int_uninit (DynIntArray
*da
)
143 dyn_array_uninit (&da
->array
, sizeof (int));
147 dyn_array_int_size (DynIntArray
*da
)
149 return da
->array
.size
;
154 dyn_array_int_empty (DynIntArray
*da
)
156 dyn_array_empty (&da
->array
);
161 dyn_array_int_add (DynIntArray
*da
, int x
)
163 int *p
= (int *)dyn_array_add (&da
->array
, sizeof (int));
168 dyn_array_int_get (DynIntArray
*da
, int x
)
170 return ((int*)da
->array
.data
)[x
];
175 dyn_array_int_set (DynIntArray
*da
, int idx
, int val
)
177 ((int*)da
->array
.data
)[idx
] = val
;
182 dyn_array_int_ensure_independent (DynIntArray
*da
)
184 dyn_array_ensure_independent (&da
->array
, sizeof (int));
188 dyn_array_int_copy (DynIntArray
*dst
, DynIntArray
*src
)
190 dyn_array_copy (&dst
->array
, &src
->array
, sizeof (int));
194 dyn_array_int_is_copy (DynIntArray
*da
)
196 return dyn_array_is_copy (&da
->array
);
202 dyn_array_ptr_init (DynPtrArray
*da
)
204 dyn_array_init (&da
->array
);
208 dyn_array_ptr_uninit (DynPtrArray
*da
)
210 #ifdef OPTIMIZATION_SINGLETON_DYN_ARRAY
211 if (da
->array
.capacity
== 1)
212 dyn_array_ptr_init (da
);
215 dyn_array_uninit (&da
->array
, sizeof (void*));
219 dyn_array_ptr_size (DynPtrArray
*da
)
221 return da
->array
.size
;
225 dyn_array_ptr_empty (DynPtrArray
*da
)
227 #ifdef OPTIMIZATION_SINGLETON_DYN_ARRAY
228 if (da
->array
.capacity
== 1)
229 dyn_array_ptr_init (da
);
232 dyn_array_empty (&da
->array
);
236 dyn_array_ptr_get (DynPtrArray
*da
, int x
)
238 #ifdef OPTIMIZATION_SINGLETON_DYN_ARRAY
239 if (da
->array
.capacity
== 1) {
241 return da
->array
.data
;
244 return ((void**)da
->array
.data
)[x
];
248 dyn_array_ptr_set (DynPtrArray
*da
, int x
, void *ptr
)
250 #ifdef OPTIMIZATION_SINGLETON_DYN_ARRAY
251 if (da
->array
.capacity
== 1) {
253 da
->array
.data
= (char*)ptr
;
257 ((void**)da
->array
.data
)[x
] = ptr
;
262 dyn_array_ptr_add (DynPtrArray
*da
, void *ptr
)
266 #ifdef OPTIMIZATION_SINGLETON_DYN_ARRAY
267 if (da
->array
.capacity
== 0) {
268 da
->array
.capacity
= 1;
270 p
= (void**)&da
->array
.data
;
271 } else if (da
->array
.capacity
== 1) {
272 void *ptr0
= da
->array
.data
;
274 dyn_array_init (&da
->array
);
275 p0
= (void **)dyn_array_add (&da
->array
, sizeof (void*));
277 p
= (void **)dyn_array_add (&da
->array
, sizeof (void*));
281 p
= (void **)dyn_array_add (&da
->array
, sizeof (void*));
286 #define dyn_array_ptr_push dyn_array_ptr_add
289 dyn_array_ptr_pop (DynPtrArray
*da
)
291 int size
= da
->array
.size
;
294 #ifdef OPTIMIZATION_SINGLETON_DYN_ARRAY
295 if (da
->array
.capacity
== 1) {
296 p
= dyn_array_ptr_get (da
, 0);
297 dyn_array_init (&da
->array
);
301 g_assert (da
->array
.capacity
> 1);
302 dyn_array_ensure_independent (&da
->array
, sizeof (void*));
303 p
= dyn_array_ptr_get (da
, size
- 1);
310 dyn_array_ptr_ensure_capacity (DynPtrArray
*da
, int capacity
)
312 #ifdef OPTIMIZATION_SINGLETON_DYN_ARRAY
313 if (capacity
== 1 && da
->array
.capacity
< 1) {
314 da
->array
.capacity
= 1;
315 } else if (da
->array
.capacity
== 1) // TODO size==1
319 void *ptr
= dyn_array_ptr_get (da
, 0);
320 da
->array
.data
= dyn_array_ensure_capacity_internal(&da
->array
, capacity
, sizeof (void*));
321 dyn_array_ptr_set (da
, 0, ptr
);
326 dyn_array_ensure_capacity (&da
->array
, capacity
, sizeof (void*));
331 dyn_array_ptr_set_all (DynPtrArray
*dst
, DynPtrArray
*src
)
333 const int copysize
= src
->array
.size
;
335 dyn_array_ptr_ensure_capacity (dst
, copysize
);
337 #ifdef OPTIMIZATION_SINGLETON_DYN_ARRAY
339 dyn_array_ptr_set (dst
, 0, dyn_array_ptr_get (src
, 0));
343 memcpy (dst
->array
.data
, src
->array
.data
, copysize
* sizeof (void*));
346 dst
->array
.size
= src
->array
.size
;