comparison src/dynarr.c @ 5038:9410323e4b0d

major dynarr fixes -------------------- ChangeLog entries follow: -------------------- src/ChangeLog addition: 2010-02-20 Ben Wing <ben@xemacs.org> * device-x.c (Fx_get_resource): * dynarr.c: * dynarr.c (Dynarr_realloc): * dynarr.c (Dynarr_newf): * dynarr.c (Dynarr_lisp_realloc): * dynarr.c (Dynarr_lisp_newf): * dynarr.c (Dynarr_resize): * dynarr.c (Dynarr_insert_many): * dynarr.c (Dynarr_delete_many): * dynarr.c (Dynarr_memory_usage): * dynarr.c (stack_like_free): * file-coding.c (coding_reader): * file-coding.c (gzip_convert): * gutter.c (output_gutter): * lisp.h: * lisp.h (Dynarr_declare): * lisp.h (DYNARR_SET_LISP_IMP): * lisp.h (CHECK_NATNUM): * profile.c (create_timing_profile_table): * redisplay-output.c (sync_rune_structs): * redisplay-output.c (sync_display_line_structs): * redisplay-output.c (redisplay_output_window): * redisplay.c: * redisplay.c (get_display_block_from_line): * redisplay.c (add_ichar_rune_1): * redisplay.c (ensure_modeline_generated): * redisplay.c (generate_displayable_area): * redisplay.c (regenerate_window): * redisplay.c (update_line_start_cache): * signal.c: * signal.c (check_quit): Lots of rewriting of dynarr code. (1) Lots of documentation added. Also fix places that referenced a now-bogus internals node concerning redisplay critical sections. (2) Rename: Dynarr_add_lisp_string -> Dynarr_add_ext_lisp_string Dynarr_set_length -> Dynarr_set_lengthr ("restricted") Dynarr_increment -> Dynarr_incrementr Dynarr_resize_if -> Dynarr_resize_to_add (3) New functions: Dynarr_elsize = dy->elsize_ Dynarr_set_length(): Set length, resizing as necessary Dynarr_set_length_and_zero(): Set length, resizing as necessary, zeroing out new elements Dynarr_increase_length(), Dynarr_increase_length_and_zero(): Optimization of Dynarr_set_length(), Dynarr_set_length_and_zero() when size is known to increase Dynarr_resize_to_fit(): Resize as necessary to fit a given length. Dynarr_set(): Set element at a given position, increasing length as necessary and setting any newly created positions to 0 (4) Use Elemcount, Bytecount. (5) Rewrite many macros as inline functions.
author Ben Wing <ben@xemacs.org>
date Sat, 20 Feb 2010 03:46:22 -0600
parents 838630c0734f
children 2a462149bd6a
comparison
equal deleted inserted replaced
5037:e70a73f9243d 5038:9410323e4b0d
23 23
24 /* Written by Ben Wing, December 1993. */ 24 /* Written by Ben Wing, December 1993. */
25 25
26 /* 26 /*
27 27
28 A "dynamic array" is a contiguous array of fixed-size elements where there 28 A "dynamic array" or "dynarr" is a contiguous array of fixed-size elements
29 is no upper limit (except available memory) on the number of elements in the 29 where there is no upper limit (except available memory) on the number of
30 array. Because the elements are maintained contiguously, space is used 30 elements in the array. Because the elements are maintained contiguously,
31 efficiently (no per-element pointers necessary) and random access to a 31 space is used efficiently (no per-element pointers necessary) and random
32 particular element is in constant time. At any one point, the block of memory 32 access to a particular element is in constant time. At any one point, the
33 that holds the array has an upper limit; if this limit is exceeded, the 33 block of memory that holds the array has an upper limit; if this limit is
34 memory is realloc()ed into a new array that is twice as big. Assuming that 34 exceeded, the memory is realloc()ed into a new array that is twice as big.
35 the time to grow the array is on the order of the new size of the array 35 Assuming that the time to grow the array is on the order of the new size of
36 block, this scheme has a provably constant amortized time (i.e. average 36 the array block, this scheme has a provably constant amortized time
37 time over all additions). 37 \(i.e. average time over all additions).
38 38
39 When you add elements or retrieve elements, pointers are used. Note that 39 When you add elements or retrieve elements, pointers are used. Note that
40 the element itself (of whatever size it is), and not the pointer to it, 40 the element itself (of whatever size it is), and not the pointer to it,
41 is stored in the array; thus you do not have to allocate any heap memory 41 is stored in the array; thus you do not have to allocate any heap memory
42 on your own. Also, returned pointers are only guaranteed to be valid 42 on your own. Also, returned pointers are only guaranteed to be valid
50 Dynarr_declare (mytype); 50 Dynarr_declare (mytype);
51 } mytype_dynarr; 51 } mytype_dynarr;
52 52
53 Use the following functions/macros: 53 Use the following functions/macros:
54 54
55
56 ************* Dynarr creation *************
57
55 void *Dynarr_new(type) 58 void *Dynarr_new(type)
56 [MACRO] Create a new dynamic-array object, with each element of the 59 [MACRO] Create a new dynamic-array object, with each element of the
57 specified type. The return value is cast to (type##_dynarr). 60 specified type. The return value is cast to (type##_dynarr).
58 This requires following the convention that types are declared in 61 This requires following the convention that types are declared in
59 such a way that this type concatenation works. In particular, TYPE 62 such a way that this type concatenation works. In particular, TYPE
60 must be a symbol, not an arbitrary C type. 63 must be a symbol, not an arbitrary C type. To make dynarrs of
64 complex types, a typedef must be declared, e.g.
65
66 typedef unsigned char *unsigned_char_ptr;
67
68 and then you can say
69
70 unsigned_char_ptr_dynarr *dyn = Dynarr_new (unsigned_char_ptr);
71
72 void *Dynarr_new2(dynarr_type, type)
73 [MACRO] Create a new dynamic-array object, with each element of the
74 specified type. The array itself is of type DYNARR_TYPE. This makes
75 it possible to create dynarrs over complex types without the need
76 to create typedefs, as described above. Use is as follows:
77
78 ucharptr_dynarr *dyn = Dynarr_new2 (ucharptr_dynarr *, unsigned char *);
79
80 Dynarr_free(d)
81 Destroy a dynamic array and the memory allocated to it.
82
83 ************* Dynarr access *************
84
85 type Dynarr_at(d, i)
86 [MACRO] Return the element at the specified index. The index must be
87 between 0 and Dynarr_largest(d), inclusive. With error-checking
88 enabled, bounds checking on the index is in the form of asserts() --
89 an out-of-bounds index causes an abort. The element itself is
90 returned, not a pointer to it.
91
92 type *Dynarr_atp(d, i)
93 [MACRO] Return a pointer to the element at the specified index.
94 Restrictions and bounds checking on the index is as for Dynarr_at.
95 The pointer may not be valid after an element is added to or
96 (conceivably) removed from the array, because this may trigger a
97 realloc() performed on the underlying dynarr storage, which may
98 involve moving the entire underlying storage to a new location in
99 memory.
100
101 type *Dynarr_begin(d)
102 [MACRO] Return a pointer to the first element in the dynarr. See
103 Dynarr_atp() for warnings about when the pointer might become invalid.
104
105 type *Dynarr_lastp(d)
106 [MACRO] Return a pointer to the last element in the dynarr. See
107 Dynarr_atp() for warnings about when the pointer might become invalid.
108
109 type *Dynarr_past_lastp(d)
110 [MACRO] Return a pointer to the beginning of the element just past the
111 last one. WARNING: This may not point to valid memory; however, the
112 byte directly before will be pointer will be valid memory. This macro
113 might be useful for various reasons, e.g. as a stopping point in a loop
114 (although Dynarr_lastp() could be used just as well) or as a place to
115 start writing elements if Dynarr_length() < Dynarr_largest().
116
117 ************* Dynarr length/size retrieval and setting *************
118
119 int Dynarr_length(d)
120 [MACRO] Return the number of elements currently in a dynamic array.
121
122 int Dynarr_largest(d)
123 [MACRO] Return the maximum value that Dynarr_length(d) would
124 ever have returned. This is used esp. in the redisplay code,
125 which reuses dynarrs for performance reasons.
126
127 int Dynarr_max(d)
128 [MACRO] Return the maximum number of elements that can fit in the
129 dynarr before it needs to be resized.
130
131 Note that Dynarr_length(d) <= Dynarr_largest(d) <= Dynarr_max(d).
132
133 Bytecount Dynarr_sizeof(d)
134 [MACRO] Return the total size of the elements currently in dynarr
135 D. This
136
137 Dynarr_set_lengthr(d, len)
138 [MACRO] Set the length of D to LEN, which must be between 0 and
139 Dynarr_largest(d), inclusive. With error-checking enabled, an
140 assertion failure will result from trying to set the length
141 to less than zero or greater than Dynarr_largest(d). The
142 restriction to Dynarr_largest() is to ensure that
143
144 Dynarr_set_length(d, len)
145 [MACRO] Set the length of D to LEN, resizing the dynarr as
146 necessary to make sure enough space is available. there are no
147 restrictions on LEN other than available memory and that it must
148 be at least 0. Note that
149
150 Dynarr_set_length_and_zero(d, len)
151 [MACRO] Like Dynarr_set_length(d, len) but also, if increasing
152 the length, zero out the memory between the old and new lengths,
153 i.e. starting just past the previous last element and up through
154 the new last element.
155
156 Dynarr_incrementr(d)
157 [MACRO] Increments the length of D by 1. Equivalent to
158 Dynarr_set_lengthr(d, Dynarr_length(d) + 1).
159
160 Dynarr_increment(d)
161 [MACRO] Increments the length of D by 1. Equivalent to
162 Dynarr_set_length(d, Dynarr_length(d) + 1).
163
164 Dynarr_reset(d)
165 [MACRO] Reset the length of a dynamic array to 0.
166
167 Dynarr_resize(d, maxval)
168 Resize the internal dynarr storage to so that it can hold at least
169 MAXVAL elements. Resizing is done using a geometric series
170 (repeatedly multiply the old maximum by a constant, normally 1.5,
171 till a large enough size is reached), so this will be efficient
172 even if resizing larger by one element at a time. This is mostly
173 an internal function.
174
175
176
177 ************* Adding/deleting elements to/from a dynarr *************
61 178
62 Dynarr_add(d, el) 179 Dynarr_add(d, el)
63 [MACRO] Add an element to the end of a dynamic array. EL is a pointer 180 [MACRO] Add an element to the end of a dynamic array. EL is a pointer
64 to the element; the element itself is stored in the array, however. 181 to the element; the element itself is stored in the array, however.
65 No function call is performed unless the array needs to be resized. 182 No function call is performed unless the array needs to be resized.
67 Dynarr_add_many(d, base, len) 184 Dynarr_add_many(d, base, len)
68 [MACRO] Add LEN elements to the end of the dynamic array. The elements 185 [MACRO] Add LEN elements to the end of the dynamic array. The elements
69 should be contiguous in memory, starting at BASE. If BASE if NULL, 186 should be contiguous in memory, starting at BASE. If BASE if NULL,
70 just make space for the elements; don't actually add them. 187 just make space for the elements; don't actually add them.
71 188
72 Dynarr_insert_many_at_start(d, base, len) 189 Dynarr_prepend_many(d, base, len)
73 [MACRO] Append LEN elements to the beginning of the dynamic array. 190 [MACRO] Prepend LEN elements to the beginning of the dynamic array.
74 The elements should be contiguous in memory, starting at BASE. 191 The elements should be contiguous in memory, starting at BASE.
75 If BASE if NULL, just make space for the elements; don't actually 192 If BASE if NULL, just make space for the elements; don't actually
76 add them. 193 add them.
77 194
78 Dynarr_insert_many(d, base, len, start) 195 Dynarr_insert_many(d, base, len, pos)
79 Insert LEN elements to the dynamic array starting at position 196 Insert LEN elements to the dynamic array starting at position
80 START. The elements should be contiguous in memory, starting at BASE. 197 POS. The elements should be contiguous in memory, starting at BASE.
81 If BASE if NULL, just make space for the elements; don't actually 198 If BASE if NULL, just make space for the elements; don't actually
82 add them. 199 add them.
83 200
201 type Dynarr_pop(d)
202 [MACRO] Pop the last element off the dynarr and return it.
203
84 Dynarr_delete(d, i) 204 Dynarr_delete(d, i)
85 [MACRO] Delete an element from the dynamic array at position I. 205 [MACRO] Delete an element from the dynamic array at position I.
86 206
87 Dynarr_delete_many(d, start, len) 207 Dynarr_delete_many(d, pos, len)
88 Delete LEN elements from the dynamic array starting at position 208 Delete LEN elements from the dynamic array starting at position
89 START. 209 POS.
210
211 Dynarr_zero_many(d, pos, len)
212 Zero out LEN elements in the dynarr D starting at position POS.
90 213
91 Dynarr_delete_by_pointer(d, p) 214 Dynarr_delete_by_pointer(d, p)
92 [MACRO] Delete an element from the dynamic array at pointer P, 215 [MACRO] Delete an element from the dynamic array at pointer P,
93 which must point within the block of memory that stores the data. 216 which must point within the block of memory that stores the data.
94 P should be obtained using Dynarr_atp(). 217 P should be obtained using Dynarr_atp().
95 218
96 int Dynarr_length(d) 219 ************* Dynarr locking *************
97 [MACRO] Return the number of elements currently in a dynamic array. 220
98 221 Dynarr_lock(d)
99 int Dynarr_largest(d) 222 Lock the dynarr against further locking or writing. With error-checking
100 [MACRO] Return the maximum value that Dynarr_length(d) would 223 enabled, any attempts to write into a locked dynarr or re-lock an
101 ever have returned. This is used esp. in the redisplay code, 224 already locked one will cause an assertion failure and abort.
102 which reuses dynarrs for performance reasons. 225
103 226 Dynarr_unlock(d)
104 type Dynarr_at(d, i) 227 Unlock a locked dynarr, allowing writing into it.
105 [MACRO] Return the element at the specified index (no bounds checking 228
106 done on the index). The element itself is returned, not a pointer 229 ************* Dynarr global variables *************
107 to it.
108
109 type *Dynarr_atp(d, i)
110 [MACRO] Return a pointer to the element at the specified index (no
111 bounds checking done on the index). The pointer may not be valid
112 after an element is added to or removed from the array.
113
114 Dynarr_reset(d)
115 [MACRO] Reset the length of a dynamic array to 0.
116
117 Dynarr_free(d)
118 Destroy a dynamic array and the memory allocated to it.
119
120 Use the following global variable:
121 230
122 Dynarr_min_size 231 Dynarr_min_size
123 Minimum allowable size for a dynamic array when it is resized. 232 Minimum allowable size for a dynamic array when it is resized.
124 233
125 */ 234 */
146 sizeof (const_Ascbyte_ptr_dynarr), 255 sizeof (const_Ascbyte_ptr_dynarr),
147 const_Ascbyte_ptr_dynarr_description_1 256 const_Ascbyte_ptr_dynarr_description_1
148 }; 257 };
149 258
150 259
151 static int Dynarr_min_size = 8; 260 static Elemcount Dynarr_min_size = 8;
152 261
153 static void 262 static void
154 Dynarr_realloc (Dynarr *dy, int new_size) 263 Dynarr_realloc (Dynarr *dy, Elemcount new_size)
155 { 264 {
156 if (DUMPEDP (dy->base)) 265 if (DUMPEDP (dy->base))
157 { 266 {
158 void *new_base = malloc (new_size * dy->elsize); 267 void *new_base = malloc (new_size * Dynarr_elsize (dy));
159 memcpy (new_base, dy->base, 268 memcpy (new_base, dy->base,
160 (Dynarr_max (dy) < new_size ? Dynarr_max (dy) : new_size) * 269 (Dynarr_max (dy) < new_size ? Dynarr_max (dy) : new_size) *
161 dy->elsize); 270 Dynarr_elsize (dy));
162 dy->base = new_base; 271 dy->base = new_base;
163 } 272 }
164 else 273 else
165 dy->base = xrealloc (dy->base, new_size * dy->elsize); 274 dy->base = xrealloc (dy->base, new_size * Dynarr_elsize (dy));
166 } 275 }
167 276
168 void * 277 void *
169 Dynarr_newf (int elsize) 278 Dynarr_newf (Bytecount elsize)
170 { 279 {
171 Dynarr *d = xnew_and_zero (Dynarr); 280 Dynarr *d = xnew_and_zero (Dynarr);
172 d->elsize = elsize; 281 d->elsize_ = elsize;
173 282
174 return d; 283 return d;
175 } 284 }
176 285
177 #ifdef NEW_GC 286 #ifdef NEW_GC
180 0, 0, 0, 0, 0, 289 0, 0, 0, 0, 0,
181 0, 290 0,
182 Dynarr); 291 Dynarr);
183 292
184 static void 293 static void
185 Dynarr_lisp_realloc (Dynarr *dy, int new_size) 294 Dynarr_lisp_realloc (Dynarr *dy, Elemcount new_size)
186 { 295 {
187 void *new_base = alloc_lrecord_array (dy->elsize, new_size, dy->lisp_imp); 296 void *new_base = alloc_lrecord_array (Dynarr_elsize (dy), new_size,
297 dy->lisp_imp);
188 if (dy->base) 298 if (dy->base)
189 memcpy (new_base, dy->base, 299 memcpy (new_base, dy->base,
190 (Dynarr_max (dy) < new_size ? Dynarr_max (dy) : new_size) * 300 (Dynarr_max (dy) < new_size ? Dynarr_max (dy) : new_size) *
191 dy->elsize); 301 Dynarr_elsize (dy));
192 dy->base = new_base; 302 dy->base = new_base;
193 } 303 }
194 304
195 void * 305 void *
196 Dynarr_lisp_newf (int elsize, 306 Dynarr_lisp_newf (Bytecount elsize,
197 const struct lrecord_implementation *dynarr_imp, 307 const struct lrecord_implementation *dynarr_imp,
198 const struct lrecord_implementation *imp) 308 const struct lrecord_implementation *imp)
199 { 309 {
200 Dynarr *d = (Dynarr *) alloc_lrecord (sizeof (Dynarr), dynarr_imp); 310 Dynarr *d = (Dynarr *) alloc_lrecord (sizeof (Dynarr), dynarr_imp);
201 d->elsize = elsize; 311 d->elsize_ = elsize;
202 d->lisp_imp = imp; 312 d->lisp_imp = imp;
203 313
204 return d; 314 return d;
205 } 315 }
206 #endif /* not NEW_GC */ 316 #endif /* not NEW_GC */
207 317
208 void 318 void
209 Dynarr_resize (void *d, Elemcount size) 319 Dynarr_resize (void *d, Elemcount size)
210 { 320 {
211 int newsize; 321 Elemcount newsize;
212 double multiplier; 322 double multiplier;
213 Dynarr *dy = (Dynarr *) Dynarr_verify (d); 323 Dynarr *dy = (Dynarr *) Dynarr_verify (d);
214 324
215 if (Dynarr_max (dy) <= 8) 325 if (Dynarr_max (dy) <= 8)
216 multiplier = 2; 326 multiplier = 2;
217 else 327 else
218 multiplier = 1.5; 328 multiplier = 1.5;
219 329
220 for (newsize = Dynarr_max (dy); newsize < size;) 330 for (newsize = Dynarr_max (dy); newsize < size;)
221 newsize = max (Dynarr_min_size, (int) (multiplier * newsize)); 331 newsize = max (Dynarr_min_size, (Elemcount) (multiplier * newsize));
222 332
223 /* Don't do anything if the array is already big enough. */ 333 /* Don't do anything if the array is already big enough. */
224 if (newsize > Dynarr_max (dy)) 334 if (newsize > Dynarr_max (dy))
225 { 335 {
226 #ifdef NEW_GC 336 #ifdef NEW_GC
233 #endif /* not NEW_GC */ 343 #endif /* not NEW_GC */
234 dy->max_ = newsize; 344 dy->max_ = newsize;
235 } 345 }
236 } 346 }
237 347
238 /* Add a number of contiguous elements to the array starting at START. */ 348 /* Add a number of contiguous elements to the array starting at POS. */
349
239 void 350 void
240 Dynarr_insert_many (void *d, const void *el, int len, int start) 351 Dynarr_insert_many (void *d, const void *base, Elemcount len, Elemcount pos)
241 { 352 {
242 Dynarr *dy = Dynarr_verify_mod (d); 353 Dynarr *dy = Dynarr_verify_mod (d);
243 354 Elemcount old_len = Dynarr_length (dy);
244 Dynarr_resize_if (dy, len);
245 355
246 /* #### This could conceivably be wrong, if code wants to access stuff 356 /* #### This could conceivably be wrong, if code wants to access stuff
247 between len and largest. */ 357 between len and largest. */
248 dynarr_checking_assert (start >= 0 && start <= Dynarr_length (dy)); 358 dynarr_checking_assert (pos >= 0 && pos <= old_len);
249 359 dynarr_checking_assert (len >= 0);
250 if (start != Dynarr_length (dy)) 360 Dynarr_increase_length (dy, old_len + len);
251 { 361
252 memmove ((char *) dy->base + (start + len)*dy->elsize, 362 if (pos != old_len)
253 (char *) dy->base + start*dy->elsize, 363 {
254 (Dynarr_length (dy) - start)*dy->elsize); 364 memmove ((Rawbyte *) dy->base + (pos + len)*Dynarr_elsize (dy),
365 (Rawbyte *) dy->base + pos*Dynarr_elsize (dy),
366 (old_len - pos)*Dynarr_elsize (dy));
255 } 367 }
256 /* Some functions call us with a value of 0 to mean "reserve space but 368 /* Some functions call us with a value of 0 to mean "reserve space but
257 don't write into it" */ 369 don't write into it" */
258 if (el) 370 if (base)
259 memcpy ((char *) dy->base + start*dy->elsize, el, len*dy->elsize); 371 memcpy ((Rawbyte *) dy->base + pos*Dynarr_elsize (dy), base,
260 372 len*Dynarr_elsize (dy));
261 Dynarr_set_length_1 (dy, Dynarr_length (dy) + len);
262 (void) Dynarr_verify_mod (dy);
263 } 373 }
264 374
265 void 375 void
266 Dynarr_delete_many (void *d, int start, int len) 376 Dynarr_delete_many (void *d, Elemcount pos, Elemcount len)
267 { 377 {
268 Dynarr *dy = Dynarr_verify_mod (d); 378 Dynarr *dy = Dynarr_verify_mod (d);
269 379
270 dynarr_checking_assert (start >= 0 && len >= 0 && 380 dynarr_checking_assert (pos >= 0 && len >= 0 &&
271 start + len <= Dynarr_length (dy)); 381 pos + len <= Dynarr_length (dy));
272 382
273 memmove ((char *) dy->base + start*dy->elsize, 383 memmove ((Rawbyte *) dy->base + pos*Dynarr_elsize (dy),
274 (char *) dy->base + (start + len)*dy->elsize, 384 (Rawbyte *) dy->base + (pos + len)*Dynarr_elsize (dy),
275 (Dynarr_length (dy) - start - len)*dy->elsize); 385 (Dynarr_length (dy) - pos - len)*Dynarr_elsize (dy));
276 386
277 Dynarr_set_length_1 (dy, Dynarr_length (dy) - len); 387 Dynarr_set_length_1 (dy, Dynarr_length (dy) - len);
278 (void) Dynarr_verify_mod (dy);
279 } 388 }
280 389
281 void 390 void
282 Dynarr_free (void *d) 391 Dynarr_free (void *d)
283 { 392 {
302 #endif /* not NEW_GC */ 411 #endif /* not NEW_GC */
303 } 412 }
304 413
305 #ifdef MEMORY_USAGE_STATS 414 #ifdef MEMORY_USAGE_STATS
306 415
307 /* Return memory usage for Dynarr D. The returned value is the total 416 /* Return memory usage for dynarr D. The returned value is the total
308 amount of bytes actually being used for the Dynarr, including all 417 amount of bytes actually being used for the dynarr, including all
309 overhead. The extra amount of space in the Dynarr that is 418 overhead. The extra amount of space in the dynarr that is
310 allocated beyond what was requested is returned in DYNARR_OVERHEAD 419 allocated beyond what was requested is returned in DYNARR_OVERHEAD
311 in STATS. The extra amount of space that malloc() allocates beyond 420 in STATS. The extra amount of space that malloc() allocates beyond
312 what was requested of it is returned in MALLOC_OVERHEAD in STATS. 421 what was requested of it is returned in MALLOC_OVERHEAD in STATS.
313 See the comment above the definition of this structure. */ 422 See the comment above the definition of this structure. */
314 423
323 requested. */ 432 requested. */
324 433
325 if (dy->base) 434 if (dy->base)
326 { 435 {
327 Bytecount malloc_used = 436 Bytecount malloc_used =
328 malloced_storage_size (dy->base, dy->elsize * Dynarr_max (dy), 0); 437 malloced_storage_size (dy->base, Dynarr_elsize (dy) * Dynarr_max (dy),
329 /* #### This may or may not be correct. Some Dynarrs would 438 0);
439 /* #### This may or may not be correct. Some dynarrs would
330 prefer that we use dy->len instead of dy->largest here. */ 440 prefer that we use dy->len instead of dy->largest here. */
331 Bytecount was_requested = dy->elsize * Dynarr_largest (dy); 441 Bytecount was_requested = Dynarr_elsize (dy) * Dynarr_largest (dy);
332 Bytecount dynarr_overhead = 442 Bytecount dynarr_overhead =
333 dy->elsize * (Dynarr_max (dy) - Dynarr_largest (dy)); 443 Dynarr_elsize (dy) * (Dynarr_max (dy) - Dynarr_largest (dy));
334 444
335 total += malloc_used; 445 total += malloc_used;
336 stats->was_requested += was_requested; 446 stats->was_requested += was_requested;
337 stats->dynarr_overhead += dynarr_overhead; 447 stats->dynarr_overhead += dynarr_overhead;
338 /* And the remainder must be malloc overhead. */ 448 /* And the remainder must be malloc overhead. */
383 } 493 }
384 494
385 void 495 void
386 stack_like_free (void *val) 496 stack_like_free (void *val)
387 { 497 {
388 int len = Dynarr_length (stack_like_in_use_list); 498 Elemcount len = Dynarr_length (stack_like_in_use_list);
389 assert (len > 0); 499 assert (len > 0);
390 /* The vast majority of times, we will be called in a last-in first-out 500 /* The vast majority of times, we will be called in a last-in first-out
391 order, and the item at the end of the list will be the one we're 501 order, and the item at the end of the list will be the one we're
392 looking for, so just check for this first and avoid any function 502 looking for, so just check for this first and avoid any function
393 calls. */ 503 calls. */