sgen-dynarray.h 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. /**
  2. * \file
  3. * Copyright 2016 Xamarin, Inc.
  4. *
  5. * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  6. */
  7. // Growable array implementation used by sgen-new-bridge and sgen-tarjan-bridge.
  8. typedef struct {
  9. int size;
  10. int capacity; /* if negative, data points to another DynArray's data */
  11. char *data;
  12. } DynArray;
  13. /*Specializations*/
  14. // 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.
  15. typedef struct {
  16. DynArray array;
  17. } DynIntArray;
  18. // 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.
  19. typedef struct {
  20. DynArray array;
  21. } DynPtrArray;
  22. typedef struct {
  23. DynArray array;
  24. } DynSCCArray;
  25. static void
  26. dyn_array_init (DynArray *da)
  27. {
  28. da->size = 0;
  29. da->capacity = 0;
  30. da->data = NULL;
  31. }
  32. static void
  33. dyn_array_uninit (DynArray *da, int elem_size)
  34. {
  35. if (da->capacity < 0) {
  36. dyn_array_init (da);
  37. return;
  38. }
  39. if (da->capacity == 0)
  40. return;
  41. sgen_free_internal_dynamic (da->data, elem_size * da->capacity, INTERNAL_MEM_BRIDGE_DATA);
  42. da->data = NULL;
  43. }
  44. static void
  45. dyn_array_empty (DynArray *da)
  46. {
  47. if (da->capacity < 0)
  48. dyn_array_init (da);
  49. else
  50. da->size = 0;
  51. }
  52. static char *
  53. dyn_array_ensure_capacity_internal (DynArray *da, int capacity, int elem_size)
  54. {
  55. if (da->capacity <= 0)
  56. da->capacity = 2;
  57. while (capacity > da->capacity)
  58. da->capacity *= 2;
  59. return (char *)sgen_alloc_internal_dynamic (elem_size * da->capacity, INTERNAL_MEM_BRIDGE_DATA, TRUE);
  60. }
  61. static void
  62. dyn_array_ensure_capacity (DynArray *da, int capacity, int elem_size)
  63. {
  64. int old_capacity = da->capacity;
  65. char *new_data;
  66. g_assert (capacity > 0);
  67. if (capacity <= old_capacity)
  68. return;
  69. new_data = dyn_array_ensure_capacity_internal (da, capacity, elem_size);
  70. memcpy (new_data, da->data, elem_size * da->size);
  71. if (old_capacity > 0)
  72. sgen_free_internal_dynamic (da->data, elem_size * old_capacity, INTERNAL_MEM_BRIDGE_DATA);
  73. da->data = new_data;
  74. }
  75. static gboolean
  76. dyn_array_is_copy (DynArray *da)
  77. {
  78. return da->capacity < 0;
  79. }
  80. static void
  81. dyn_array_ensure_independent (DynArray *da, int elem_size)
  82. {
  83. if (!dyn_array_is_copy (da))
  84. return;
  85. dyn_array_ensure_capacity (da, da->size, elem_size);
  86. g_assert (da->capacity > 0);
  87. }
  88. static void*
  89. dyn_array_add (DynArray *da, int elem_size)
  90. {
  91. void *p;
  92. dyn_array_ensure_capacity (da, da->size + 1, elem_size);
  93. p = da->data + da->size * elem_size;
  94. ++da->size;
  95. return p;
  96. }
  97. static void
  98. dyn_array_copy (DynArray *dst, DynArray *src, int elem_size)
  99. {
  100. dyn_array_uninit (dst, elem_size);
  101. if (src->size == 0)
  102. return;
  103. dst->size = src->size;
  104. dst->capacity = -1;
  105. dst->data = src->data;
  106. }
  107. /* int */
  108. static inline void
  109. dyn_array_int_init (DynIntArray *da)
  110. {
  111. dyn_array_init (&da->array);
  112. }
  113. static inline void
  114. dyn_array_int_uninit (DynIntArray *da)
  115. {
  116. dyn_array_uninit (&da->array, sizeof (int));
  117. }
  118. static inline int
  119. dyn_array_int_size (DynIntArray *da)
  120. {
  121. return da->array.size;
  122. }
  123. #ifdef NEW_XREFS
  124. static void
  125. dyn_array_int_empty (DynIntArray *da)
  126. {
  127. dyn_array_empty (&da->array);
  128. }
  129. #endif
  130. static inline void
  131. dyn_array_int_add (DynIntArray *da, int x)
  132. {
  133. int *p = (int *)dyn_array_add (&da->array, sizeof (int));
  134. *p = x;
  135. }
  136. static inline int
  137. dyn_array_int_get (DynIntArray *da, int x)
  138. {
  139. return ((int*)da->array.data)[x];
  140. }
  141. #ifdef NEW_XREFS
  142. static void
  143. dyn_array_int_set (DynIntArray *da, int idx, int val)
  144. {
  145. ((int*)da->array.data)[idx] = val;
  146. }
  147. #endif
  148. static inline void
  149. dyn_array_int_ensure_independent (DynIntArray *da)
  150. {
  151. dyn_array_ensure_independent (&da->array, sizeof (int));
  152. }
  153. static inline void
  154. dyn_array_int_copy (DynIntArray *dst, DynIntArray *src)
  155. {
  156. dyn_array_copy (&dst->array, &src->array, sizeof (int));
  157. }
  158. static inline gboolean
  159. dyn_array_int_is_copy (DynIntArray *da)
  160. {
  161. return dyn_array_is_copy (&da->array);
  162. }
  163. /* ptr */
  164. static inline void
  165. dyn_array_ptr_init (DynPtrArray *da)
  166. {
  167. dyn_array_init (&da->array);
  168. }
  169. static void
  170. dyn_array_ptr_uninit (DynPtrArray *da)
  171. {
  172. #ifdef OPTIMIZATION_SINGLETON_DYN_ARRAY
  173. if (da->array.capacity == 1)
  174. dyn_array_ptr_init (da);
  175. else
  176. #endif
  177. dyn_array_uninit (&da->array, sizeof (void*));
  178. }
  179. static int
  180. dyn_array_ptr_size (DynPtrArray *da)
  181. {
  182. return da->array.size;
  183. }
  184. static void
  185. dyn_array_ptr_empty (DynPtrArray *da)
  186. {
  187. #ifdef OPTIMIZATION_SINGLETON_DYN_ARRAY
  188. if (da->array.capacity == 1)
  189. dyn_array_ptr_init (da);
  190. else
  191. #endif
  192. dyn_array_empty (&da->array);
  193. }
  194. static void*
  195. dyn_array_ptr_get (DynPtrArray *da, int x)
  196. {
  197. #ifdef OPTIMIZATION_SINGLETON_DYN_ARRAY
  198. if (da->array.capacity == 1) {
  199. g_assert (x == 0);
  200. return da->array.data;
  201. }
  202. #endif
  203. return ((void**)da->array.data)[x];
  204. }
  205. static inline void
  206. dyn_array_ptr_set (DynPtrArray *da, int x, void *ptr)
  207. {
  208. #ifdef OPTIMIZATION_SINGLETON_DYN_ARRAY
  209. if (da->array.capacity == 1) {
  210. g_assert (x == 0);
  211. da->array.data = (char*)ptr;
  212. } else
  213. #endif
  214. {
  215. ((void**)da->array.data)[x] = ptr;
  216. }
  217. }
  218. static void
  219. dyn_array_ptr_add (DynPtrArray *da, void *ptr)
  220. {
  221. void **p;
  222. #ifdef OPTIMIZATION_SINGLETON_DYN_ARRAY
  223. if (da->array.capacity == 0) {
  224. da->array.capacity = 1;
  225. da->array.size = 1;
  226. p = (void**)&da->array.data;
  227. } else if (da->array.capacity == 1) {
  228. void *ptr0 = da->array.data;
  229. void **p0;
  230. dyn_array_init (&da->array);
  231. p0 = (void **)dyn_array_add (&da->array, sizeof (void*));
  232. *p0 = ptr0;
  233. p = (void **)dyn_array_add (&da->array, sizeof (void*));
  234. } else
  235. #endif
  236. {
  237. p = (void **)dyn_array_add (&da->array, sizeof (void*));
  238. }
  239. *p = ptr;
  240. }
  241. #define dyn_array_ptr_push dyn_array_ptr_add
  242. static void*
  243. dyn_array_ptr_pop (DynPtrArray *da)
  244. {
  245. int size = da->array.size;
  246. void *p;
  247. g_assert (size > 0);
  248. #ifdef OPTIMIZATION_SINGLETON_DYN_ARRAY
  249. if (da->array.capacity == 1) {
  250. p = dyn_array_ptr_get (da, 0);
  251. dyn_array_init (&da->array);
  252. } else
  253. #endif
  254. {
  255. g_assert (da->array.capacity > 1);
  256. dyn_array_ensure_independent (&da->array, sizeof (void*));
  257. p = dyn_array_ptr_get (da, size - 1);
  258. --da->array.size;
  259. }
  260. return p;
  261. }
  262. static void
  263. dyn_array_ptr_ensure_capacity (DynPtrArray *da, int capacity)
  264. {
  265. #ifdef OPTIMIZATION_SINGLETON_DYN_ARRAY
  266. if (capacity == 1 && da->array.capacity < 1) {
  267. da->array.capacity = 1;
  268. } else if (da->array.capacity == 1) // TODO size==1
  269. {
  270. if (capacity > 1)
  271. {
  272. void *ptr = dyn_array_ptr_get (da, 0);
  273. da->array.data = dyn_array_ensure_capacity_internal(&da->array, capacity, sizeof (void*));
  274. dyn_array_ptr_set (da, 0, ptr);
  275. }
  276. }
  277. #endif
  278. {
  279. dyn_array_ensure_capacity (&da->array, capacity, sizeof (void*));
  280. }
  281. }
  282. static inline void
  283. dyn_array_ptr_set_all (DynPtrArray *dst, DynPtrArray *src)
  284. {
  285. const int copysize = src->array.size;
  286. if (copysize > 0) {
  287. dyn_array_ptr_ensure_capacity (dst, copysize);
  288. #ifdef OPTIMIZATION_SINGLETON_DYN_ARRAY
  289. if (copysize == 1) {
  290. dyn_array_ptr_set (dst, 0, dyn_array_ptr_get (src, 0));
  291. } else
  292. #endif
  293. {
  294. memcpy (dst->array.data, src->array.data, copysize * sizeof (void*));
  295. }
  296. }
  297. dst->array.size = src->array.size;
  298. }