@@ -567,22 +567,28 @@ void *gc_realloc(void *ptr_in, mp_uint_t n_bytes) {
567
567
// compute number of new blocks that are requested
568
568
mp_uint_t new_blocks = (n_bytes + BYTES_PER_BLOCK - 1 ) / BYTES_PER_BLOCK ;
569
569
570
- // get the number of consecutive tail blocks and
571
- // the number of free blocks after last tail block
572
- // stop if we reach (or are at) end of heap
570
+ // Get the total number of consecutive blocks that are already allocated to
571
+ // this chunk of memory, and then count the number of free blocks following
572
+ // it. Stop if we reach the end of the heap, or if we find enough extra
573
+ // free blocks to satisfy the realloc. Note that we need to compute the
574
+ // total size of the existing memory chunk so we can correctly and
575
+ // efficiently shrink it (see below for shrinking code).
573
576
mp_uint_t n_free = 0 ;
574
577
mp_uint_t n_blocks = 1 ; // counting HEAD block
575
578
mp_uint_t max_block = gc_alloc_table_byte_len * BLOCKS_PER_ATB ;
576
- while (block + n_blocks + n_free < max_block ) {
577
- if (n_blocks + n_free >= new_blocks ) {
578
- // stop as soon as we find enough blocks for n_bytes
579
- break ;
579
+ for (mp_uint_t bl = block + n_blocks ; bl < max_block ; bl ++ ) {
580
+ byte block_type = ATB_GET_KIND (bl );
581
+ if (block_type == AT_TAIL ) {
582
+ n_blocks ++ ;
583
+ continue ;
580
584
}
581
- byte block_type = ATB_GET_KIND (block + n_blocks + n_free );
582
- switch (block_type ) {
583
- case AT_FREE : n_free ++ ; continue ;
584
- case AT_TAIL : n_blocks ++ ; continue ;
585
- case AT_MARK : assert (0 );
585
+ if (block_type == AT_FREE ) {
586
+ n_free ++ ;
587
+ if (n_blocks + n_free >= new_blocks ) {
588
+ // stop as soon as we find enough blocks for n_bytes
589
+ break ;
590
+ }
591
+ continue ;
586
592
}
587
593
break ;
588
594
}
@@ -595,7 +601,7 @@ void *gc_realloc(void *ptr_in, mp_uint_t n_bytes) {
595
601
// check if we can shrink the allocated area
596
602
if (new_blocks < n_blocks ) {
597
603
// free unneeded tail blocks
598
- for (mp_uint_t bl = block + new_blocks ; ATB_GET_KIND ( bl ) == AT_TAIL ; bl ++ ) {
604
+ for (mp_uint_t bl = block + new_blocks , count = n_blocks - new_blocks ; count > 0 ; bl ++ , count -- ) {
599
605
ATB_ANY_TO_FREE (bl );
600
606
}
601
607
0 commit comments