4747 * answer. When ar is NULL (e.g. during arFree) tracking is skipped.
4848 * -------------------------------------------------------------------------- */
4949
50- static inline void arTrackAlloc (redisArray * ar , void * ptr ) {
51- if (ar ) ar -> alloc_size += zmalloc_size (ptr );
50+ static inline void * arAllocAndTrack (redisArray * ar , size_t size ) {
51+ size_t usable ;
52+ void * ptr = zmalloc_usable (size , & usable );
53+ if (ar ) ar -> alloc_size += usable ;
54+ return ptr ;
55+ }
56+ static inline void * arCallocAndTrack (redisArray * ar , size_t size ) {
57+ size_t usable ;
58+ void * ptr = zcalloc_usable (size , & usable );
59+ if (ar ) ar -> alloc_size += usable ;
60+ return ptr ;
5261}
53- static inline void arTrackFree (redisArray * ar , void * ptr ) {
54- if (ar ) ar -> alloc_size -= zmalloc_size (ptr );
62+ static inline void arFreeAndTrack (redisArray * ar , void * ptr ) {
63+ size_t usable ;
64+ zfree_usable (ptr , & usable );
65+ if (ar ) ar -> alloc_size -= usable ;
5566}
56- static inline void arTrackRealloc (redisArray * ar , size_t old_size , void * ptr ) {
57- if (ar ) ar -> alloc_size += zmalloc_size (ptr ) - old_size ;
67+ static inline void * arReallocAndTrack (redisArray * ar , void * ptr , size_t size ) {
68+ size_t usable , old_usable ;
69+ void * newptr = zrealloc_usable (ptr , size , & usable , & old_usable );
70+ if (ar ) ar -> alloc_size += usable - old_usable ;
71+ return newptr ;
5872}
5973
6074/* Track a tagged value entering/leaving the array (arString bookkeeping). */
@@ -213,8 +227,7 @@ arSlice *arSliceDenseNew(redisArray *ar, uint32_t rel_idx, uint32_t slice_size)
213227 offset = slice_size - winsize ;
214228 }
215229
216- arSlice * s = zmalloc (arDenseAllocSize (winsize ));
217- arTrackAlloc (ar , s );
230+ arSlice * s = arAllocAndTrack (ar , arDenseAllocSize (winsize ));
218231 s -> encoding = AR_SLICE_DENSE ;
219232 s -> count = 0 ;
220233 s -> layout .dense .offset = offset ;
@@ -242,8 +255,7 @@ void arSparseSetupPointers(arSlice *s) {
242255/* Create a new sparse slice */
243256arSlice * arSliceSparseNew (redisArray * ar ) {
244257 uint32_t cap = (ArraySparseKMax < 4 ) ? ArraySparseKMax : 4 ;
245- arSlice * s = zmalloc (arSparseAllocSize (cap ));
246- arTrackAlloc (ar , s );
258+ arSlice * s = arAllocAndTrack (ar , arSparseAllocSize (cap ));
247259 s -> encoding = AR_SLICE_SPARSE ;
248260 s -> count = 0 ;
249261 s -> layout .sparse .cap = cap ;
@@ -269,8 +281,7 @@ void arSliceFree(redisArray *ar, arSlice *s) {
269281 arFreePtr (values [i ]);
270282 }
271283 }
272- arTrackFree (ar , s );
273- zfree (s );
284+ arFreeAndTrack (ar , s );
274285}
275286
276287/* Grow dense slice to accommodate rel_idx (right growth) */
@@ -295,9 +306,7 @@ arSlice *arSliceDenseGrowRight(redisArray *ar, arSlice *s, uint32_t rel_idx, uin
295306 * the dense allocation without relocating existing items ourselves. */
296307 if (new_offset == s -> layout .dense .offset ) {
297308 uint32_t old_winsize = s -> layout .dense .winsize ;
298- size_t old_size = zmalloc_size (s );
299- arSlice * ns = zrealloc (s , arDenseAllocSize (new_winsize ));
300- arTrackRealloc (ar , old_size , ns );
309+ arSlice * ns = arReallocAndTrack (ar , s , arDenseAllocSize (new_winsize ));
301310 ns -> layout .dense .winsize = new_winsize ;
302311 ns -> layout .dense .items = (void * * )(ns + 1 );
303312
@@ -308,8 +317,7 @@ arSlice *arSliceDenseGrowRight(redisArray *ar, arSlice *s, uint32_t rel_idx, uin
308317 }
309318
310319 /* Data copy path: offset moved, so we allocate a new slice and copy. */
311- arSlice * ns = zmalloc (arDenseAllocSize (new_winsize ));
312- arTrackAlloc (ar , ns );
320+ arSlice * ns = arAllocAndTrack (ar , arDenseAllocSize (new_winsize ));
313321 ns -> encoding = AR_SLICE_DENSE ;
314322 ns -> count = s -> count ;
315323 ns -> layout .dense .offset = new_offset ;
@@ -324,8 +332,7 @@ arSlice *arSliceDenseGrowRight(redisArray *ar, arSlice *s, uint32_t rel_idx, uin
324332 serverAssert (shift + s -> layout .dense .winsize <= new_winsize );
325333 memcpy (ns -> layout .dense .items + shift , s -> layout .dense .items , s -> layout .dense .winsize * sizeof (void * ));
326334
327- arTrackFree (ar , s );
328- zfree (s );
335+ arFreeAndTrack (ar , s );
329336 return ns ;
330337}
331338
@@ -348,8 +355,7 @@ arSlice *arSliceDenseGrowLeft(redisArray *ar, arSlice *s, uint32_t rel_idx, uint
348355 if (new_offset < 0 ) new_offset = 0 ;
349356 if (new_winsize == slice_size ) new_offset = 0 ;
350357
351- arSlice * ns = zmalloc (arDenseAllocSize (new_winsize ));
352- arTrackAlloc (ar , ns );
358+ arSlice * ns = arAllocAndTrack (ar , arDenseAllocSize (new_winsize ));
353359 ns -> encoding = AR_SLICE_DENSE ;
354360 ns -> count = s -> count ;
355361 ns -> layout .dense .offset = (uint32_t )new_offset ;
@@ -363,8 +369,7 @@ arSlice *arSliceDenseGrowLeft(redisArray *ar, arSlice *s, uint32_t rel_idx, uint
363369 serverAssert (shift + s -> layout .dense .winsize <= new_winsize );
364370 memcpy (ns -> layout .dense .items + shift , s -> layout .dense .items , s -> layout .dense .winsize * sizeof (void * ));
365371
366- arTrackFree (ar , s );
367- zfree (s );
372+ arFreeAndTrack (ar , s );
368373 return ns ;
369374}
370375
@@ -401,8 +406,7 @@ uint32_t arSparseFindPos(arSlice *s, uint16_t rel_idx, int *found) {
401406/* Promote sparse slice to dense. */
402407arSlice * arSparsePromote (redisArray * ar , arSlice * s , uint32_t slice_size ) {
403408 if (s -> count == 0 ) {
404- arTrackFree (ar , s );
405- zfree (s );
409+ arFreeAndTrack (ar , s );
406410 return arSliceDenseNew (ar , 0 , slice_size );
407411 }
408412
@@ -425,8 +429,7 @@ arSlice *arSparsePromote(redisArray *ar, arSlice *s, uint32_t slice_size) {
425429 offset = slice_size - winsize ;
426430 }
427431
428- arSlice * d = zmalloc (arDenseAllocSize (winsize ));
429- arTrackAlloc (ar , d );
432+ arSlice * d = arAllocAndTrack (ar , arDenseAllocSize (winsize ));
430433 d -> encoding = AR_SLICE_DENSE ;
431434 d -> count = s -> count ;
432435 d -> layout .dense .offset = offset ;
@@ -443,8 +446,7 @@ arSlice *arSparsePromote(redisArray *ar, arSlice *s, uint32_t slice_size) {
443446 d -> layout .dense .items [offsets [i ] - offset ] = values [i ];
444447 }
445448
446- arTrackFree (ar , s );
447- zfree (s );
449+ arFreeAndTrack (ar , s );
448450 return d ;
449451}
450452
@@ -468,8 +470,7 @@ arSlice *arDenseMaybeDemote(redisArray *ar, arSlice *d) {
468470 if (dense_bytes < sparse_bytes * 5 / 4 ) return d ;
469471
470472 /* Demote it. */
471- arSlice * s = zmalloc (arSparseAllocSize (ArraySparseKMin ));
472- arTrackAlloc (ar , s );
473+ arSlice * s = arAllocAndTrack (ar , arSparseAllocSize (ArraySparseKMin ));
473474 s -> encoding = AR_SLICE_SPARSE ;
474475 s -> count = 0 ;
475476 s -> layout .sparse .cap = ArraySparseKMin ;
@@ -486,8 +487,7 @@ arSlice *arDenseMaybeDemote(redisArray *ar, arSlice *d) {
486487 }
487488 }
488489
489- arTrackFree (ar , d );
490- zfree (d );
490+ arFreeAndTrack (ar , d );
491491 return s ;
492492}
493493
@@ -584,9 +584,7 @@ arSlice **arSuperDirEnsureSlot(redisArray *ar, uint64_t slice_id) {
584584 if (ar -> sdir_len >= ar -> sdir_cap ) {
585585 /* Grow superdir array */
586586 uint32_t new_cap = ar -> sdir_cap ? ar -> sdir_cap * 2 : 4 ;
587- size_t old_size = ar -> superdir ? zmalloc_size (ar -> superdir ) : 0 ;
588- ar -> superdir = zrealloc (ar -> superdir , new_cap * sizeof (arSDirEntry ));
589- arTrackRealloc (ar , old_size , ar -> superdir );
587+ ar -> superdir = arReallocAndTrack (ar , ar -> superdir , new_cap * sizeof (arSDirEntry ));
590588 ar -> sdir_cap = new_cap ;
591589 }
592590
@@ -599,8 +597,7 @@ arSlice **arSuperDirEnsureSlot(redisArray *ar, uint64_t slice_id) {
599597 /* Initialize new entry */
600598 ar -> superdir [pos ].block_id = block_id ;
601599 ar -> superdir [pos ].count = 0 ;
602- ar -> superdir [pos ].slots = zcalloc (AR_SUPER_BLOCK_SLOTS * sizeof (arSlice * ));
603- arTrackAlloc (ar , ar -> superdir [pos ].slots );
600+ ar -> superdir [pos ].slots = arCallocAndTrack (ar , AR_SUPER_BLOCK_SLOTS * sizeof (arSlice * ));
604601 ar -> sdir_len ++ ;
605602 }
606603
@@ -622,8 +619,7 @@ arSDirEntry *arSuperDirGetEntry(redisArray *ar, uint64_t slice_id) {
622619 * Frees the slice-pointer table, compacts remaining entries (keeping order by
623620 * block_id), and decrements ar->sdir_len. */
624621void arSuperDirRemoveBlock (redisArray * ar , uint32_t pos ) {
625- arTrackFree (ar , ar -> superdir [pos ].slots );
626- zfree (ar -> superdir [pos ].slots );
622+ arFreeAndTrack (ar , ar -> superdir [pos ].slots );
627623 if (pos < ar -> sdir_len - 1 ) {
628624 memmove (ar -> superdir + pos , ar -> superdir + pos + 1 ,
629625 (ar -> sdir_len - pos - 1 ) * sizeof (arSDirEntry ));
@@ -636,14 +632,12 @@ void arSuperDirRemoveBlock(redisArray *ar, uint32_t pos) {
636632void arPromoteToSuperDir (redisArray * ar ) {
637633 ar -> sdir_cap = 4 ;
638634 ar -> sdir_len = 0 ;
639- ar -> superdir = zmalloc (ar -> sdir_cap * sizeof (arSDirEntry ));
640- arTrackAlloc (ar , ar -> superdir );
635+ ar -> superdir = arAllocAndTrack (ar , ar -> sdir_cap * sizeof (arSDirEntry ));
641636
642637 /* Copy existing flat dir content into block 0 */
643638 if (ar -> dir_alloc > 0 ) {
644639 ar -> superdir [0 ].block_id = 0 ;
645- ar -> superdir [0 ].slots = zcalloc (AR_SUPER_BLOCK_SLOTS * sizeof (arSlice * ));
646- arTrackAlloc (ar , ar -> superdir [0 ].slots );
640+ ar -> superdir [0 ].slots = arCallocAndTrack (ar , AR_SUPER_BLOCK_SLOTS * sizeof (arSlice * ));
647641 ar -> superdir [0 ].count = 0 ;
648642 ar -> sdir_len = 1 ;
649643
@@ -655,8 +649,7 @@ void arPromoteToSuperDir(redisArray *ar) {
655649 }
656650
657651 /* Free old flat directory */
658- if (ar -> dir ) arTrackFree (ar , ar -> dir );
659- zfree (ar -> dir );
652+ if (ar -> dir ) arFreeAndTrack (ar , ar -> dir );
660653 ar -> dir = NULL ;
661654 ar -> dir_alloc = 0 ;
662655}
@@ -687,9 +680,7 @@ void arDirGrow(redisArray *ar, uint64_t slice_id) {
687680 new_alloc <<= 1 ;
688681 }
689682
690- size_t old_size = ar -> dir ? zmalloc_size (ar -> dir ) : 0 ;
691- arSlice * * new_dir = zrealloc (ar -> dir , new_alloc * sizeof (arSlice * ));
692- arTrackRealloc (ar , old_size , new_dir );
683+ arSlice * * new_dir = arReallocAndTrack (ar , ar -> dir , new_alloc * sizeof (arSlice * ));
693684
694685 /* Zero-fill new slots */
695686 memset (new_dir + ar -> dir_alloc , 0 , (new_alloc - ar -> dir_alloc ) * sizeof (arSlice * ));
@@ -711,9 +702,7 @@ void arDirMaybeShrink(redisArray *ar) {
711702 while (new_alloc <= ar -> dir_highest_used ) new_alloc <<= 1 ;
712703 if (new_alloc >= ar -> dir_alloc ) return ;
713704
714- size_t old_size = zmalloc_size (ar -> dir );
715- ar -> dir = zrealloc (ar -> dir , new_alloc * sizeof (arSlice * ));
716- arTrackRealloc (ar , old_size , ar -> dir );
705+ ar -> dir = arReallocAndTrack (ar , ar -> dir , new_alloc * sizeof (arSlice * ));
717706 ar -> dir_alloc = new_alloc ;
718707}
719708
@@ -1120,8 +1109,7 @@ void arFree(redisArray *ar) {
11201109arSlice * arSliceDup (redisArray * dup_ar , arSlice * s ) {
11211110 if (s -> encoding == AR_SLICE_DENSE ) {
11221111 size_t sz = arDenseAllocSize (s -> layout .dense .winsize );
1123- arSlice * nd = zmalloc (sz );
1124- arTrackAlloc (dup_ar , nd );
1112+ arSlice * nd = arAllocAndTrack (dup_ar , sz );
11251113 memcpy (nd , s , sizeof (arSlice ));
11261114 nd -> layout .dense .items = (void * * )(nd + 1 );
11271115 memcpy (nd -> layout .dense .items , s -> layout .dense .items ,
@@ -1137,8 +1125,7 @@ arSlice *arSliceDup(redisArray *dup_ar, arSlice *s) {
11371125 return nd ;
11381126 } else {
11391127 size_t sz = arSparseAllocSize (s -> layout .sparse .cap );
1140- arSlice * nsp = zmalloc (sz );
1141- arTrackAlloc (dup_ar , nsp );
1128+ arSlice * nsp = arAllocAndTrack (dup_ar , sz );
11421129 memcpy (nsp , s , sizeof (arSlice ));
11431130 arSparseSetupPointers (nsp );
11441131 memcpy (nsp -> layout .sparse .offsets , s -> layout .sparse .offsets ,
@@ -1174,17 +1161,15 @@ redisArray *arDup(redisArray *ar) {
11741161 if (ar -> superdir ) {
11751162 /* Superdir mode */
11761163 dup -> dir = NULL ;
1177- dup -> superdir = zmalloc (ar -> sdir_cap * sizeof (arSDirEntry ));
1178- arTrackAlloc (dup , dup -> superdir );
1164+ dup -> superdir = arAllocAndTrack (dup , ar -> sdir_cap * sizeof (arSDirEntry ));
11791165
11801166 for (uint32_t i = 0 ; i < ar -> sdir_len ; i ++ ) {
11811167 arSDirEntry * src = ar -> superdir + i ;
11821168 arSDirEntry * dst = dup -> superdir + i ;
11831169
11841170 dst -> block_id = src -> block_id ;
11851171 dst -> count = src -> count ;
1186- dst -> slots = zcalloc (AR_SUPER_BLOCK_SLOTS * sizeof (arSlice * ));
1187- arTrackAlloc (dup , dst -> slots );
1172+ dst -> slots = arCallocAndTrack (dup , AR_SUPER_BLOCK_SLOTS * sizeof (arSlice * ));
11881173
11891174 for (uint32_t j = 0 ; j < AR_SUPER_BLOCK_SLOTS ; j ++ ) {
11901175 if (src -> slots [j ]) {
@@ -1195,8 +1180,7 @@ redisArray *arDup(redisArray *ar) {
11951180 } else if (ar -> dir_alloc > 0 ) {
11961181 /* Flat mode */
11971182 dup -> superdir = NULL ;
1198- dup -> dir = zmalloc (ar -> dir_alloc * sizeof (arSlice * ));
1199- arTrackAlloc (dup , dup -> dir );
1183+ dup -> dir = arAllocAndTrack (dup , ar -> dir_alloc * sizeof (arSlice * ));
12001184 memset (dup -> dir , 0 , ar -> dir_alloc * sizeof (arSlice * ));
12011185
12021186 for (uint64_t i = 0 ; i < ar -> dir_alloc ; i ++ ) {
@@ -1329,8 +1313,7 @@ void arSet(redisArray *ar, uint64_t idx, void *v) {
13291313 * point in growing more than kmax, so we clamp to kmax. */
13301314 uint32_t new_cap = s -> layout .sparse .cap * 2 ;
13311315 if (new_cap > ArraySparseKMax ) new_cap = ArraySparseKMax ;
1332- arSlice * ns = zmalloc (arSparseAllocSize (new_cap ));
1333- arTrackAlloc (ar , ns );
1316+ arSlice * ns = arAllocAndTrack (ar , arSparseAllocSize (new_cap ));
13341317 ns -> encoding = AR_SLICE_SPARSE ;
13351318 ns -> count = s -> count ;
13361319 ns -> layout .sparse .cap = new_cap ;
@@ -1344,8 +1327,7 @@ void arSet(redisArray *ar, uint64_t idx, void *v) {
13441327 memcpy (new_offsets ,old_offsets ,s -> count * sizeof (uint16_t ));
13451328 memcpy (new_values ,old_values ,s -> count * sizeof (void * ));
13461329
1347- arTrackFree (ar , s );
1348- zfree (s );
1330+ arFreeAndTrack (ar , s );
13491331 s = ns ;
13501332 arSetSlice (ar , slice_id , s );
13511333 offsets = new_offsets ;
0 commit comments