@@ -567,22 +567,28 @@ void *gc_realloc(void *ptr_in, mp_uint_t n_bytes) {
567567 // compute number of new blocks that are requested
568568 mp_uint_t new_blocks = (n_bytes + BYTES_PER_BLOCK - 1 ) / BYTES_PER_BLOCK ;
569569
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).
573576 mp_uint_t n_free = 0 ;
574577 mp_uint_t n_blocks = 1 ; // counting HEAD block
575578 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 ;
580584 }
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 ;
586592 }
587593 break ;
588594 }
@@ -595,7 +601,7 @@ void *gc_realloc(void *ptr_in, mp_uint_t n_bytes) {
595601 // check if we can shrink the allocated area
596602 if (new_blocks < n_blocks ) {
597603 // 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 -- ) {
599605 ATB_ANY_TO_FREE (bl );
600606 }
601607
0 commit comments