Mercurial > hg > xemacs-beta
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. */ |