From dde739d364b0faf48e74a88b65dc2468a3aaf64b Mon Sep 17 00:00:00 2001 From: Damien George Date: Sun, 20 Apr 2014 18:16:25 +0100 Subject: [PATCH] py, gc: Further simplify coding-style of gc_realloc. No logic changes, just coding style to make it easy to read. --- py/gc.c | 139 +++++++++++++++++++++++++++++++------------------------- 1 file changed, 76 insertions(+), 63 deletions(-) diff --git a/py/gc.c b/py/gc.c index bcf6cfcdda..2930e90110 100644 --- a/py/gc.c +++ b/py/gc.c @@ -459,78 +459,91 @@ void *gc_realloc(void *ptr_in, machine_uint_t n_bytes) { return NULL; } - void *ptr_out = NULL; - machine_uint_t ptr = (machine_uint_t)ptr_in; - + // check for pure allocation if (ptr_in == NULL) { return gc_alloc(n_bytes, false); } - machine_uint_t new_blocks = (n_bytes + BYTES_PER_BLOCK) / BYTES_PER_BLOCK; + machine_uint_t ptr = (machine_uint_t)ptr_in; + + // sanity check the ptr + if (!VERIFY_PTR(ptr)) { + return NULL; + } + // get first block machine_uint_t block = BLOCK_FROM_PTR(ptr); - // Sabity checks - if (VERIFY_PTR(ptr) && ATB_GET_KIND(block) == AT_HEAD) { - - byte block_type; - machine_uint_t n_free = 0; - machine_uint_t n_blocks = 1; // counting HEAD block - machine_uint_t max_block = gc_alloc_table_byte_len * BLOCKS_PER_ATB; - - // get the number of consecutive tail blocks and - // the number of free blocks after last tail block - // stop if we reach (or are at) end of heap - while (block + n_blocks + n_free < max_block) { - if (n_blocks + n_free >= new_blocks) { - // stop as soon as we find enough blocks for n_bytes - break; - } - block_type = ATB_GET_KIND(block + n_blocks + n_free); - switch (block_type) { - case AT_FREE: n_free++; continue; - case AT_TAIL: n_blocks++; continue; - case AT_MARK: assert(0); - } - break; - } - - if (new_blocks == n_blocks) { - return ptr_in; - } - - if (new_blocks < n_blocks) { - // free unneeded tail blocks - for (machine_uint_t bl = block + new_blocks; ATB_GET_KIND(bl) == AT_TAIL; bl++) { - ATB_ANY_TO_FREE(bl); - } - return ptr_in; - - // check if we can expand in place - } else if (new_blocks <= n_blocks + n_free) { - // mark few more blocks as used tail - for (machine_uint_t bl = block + n_blocks; bl < block + new_blocks; bl++) { - assert(ATB_GET_KIND(bl) == AT_FREE); - ATB_FREE_TO_TAIL(bl); - } - return ptr_in; - - // try to find a new contiguous chain - } else if ((ptr_out = gc_alloc(n_bytes, -#if MICROPY_ENABLE_FINALISER - FTB_GET(block) -#else - false -#endif - )) != NULL) { - DEBUG_printf("gc_realloc: allocating new block\n"); - memcpy(ptr_out, ptr_in, n_blocks * BYTES_PER_BLOCK); - gc_free(ptr_in); - return ptr_out; - } + // sanity check the ptr is pointing to the head of a block + if (ATB_GET_KIND(block) != AT_HEAD) { + return NULL; } - return NULL; + // compute number of new blocks that are requested + machine_uint_t new_blocks = (n_bytes + BYTES_PER_BLOCK) / BYTES_PER_BLOCK; + + // get the number of consecutive tail blocks and + // the number of free blocks after last tail block + // stop if we reach (or are at) end of heap + machine_uint_t n_free = 0; + machine_uint_t n_blocks = 1; // counting HEAD block + machine_uint_t max_block = gc_alloc_table_byte_len * BLOCKS_PER_ATB; + while (block + n_blocks + n_free < max_block) { + if (n_blocks + n_free >= new_blocks) { + // stop as soon as we find enough blocks for n_bytes + break; + } + byte block_type = ATB_GET_KIND(block + n_blocks + n_free); + switch (block_type) { + case AT_FREE: n_free++; continue; + case AT_TAIL: n_blocks++; continue; + case AT_MARK: assert(0); + } + break; + } + + // return original ptr if it already has the requested number of blocks + if (new_blocks == n_blocks) { + return ptr_in; + } + + // check if we can shrink the allocated area + if (new_blocks < n_blocks) { + // free unneeded tail blocks + for (machine_uint_t bl = block + new_blocks; ATB_GET_KIND(bl) == AT_TAIL; bl++) { + ATB_ANY_TO_FREE(bl); + } + return ptr_in; + } + + // check if we can expand in place + if (new_blocks <= n_blocks + n_free) { + // mark few more blocks as used tail + for (machine_uint_t bl = block + n_blocks; bl < block + new_blocks; bl++) { + assert(ATB_GET_KIND(bl) == AT_FREE); + ATB_FREE_TO_TAIL(bl); + } + return ptr_in; + } + + // can't resize inplace; try to find a new contiguous chain + void *ptr_out = gc_alloc(n_bytes, +#if MICROPY_ENABLE_FINALISER + FTB_GET(block) +#else + false +#endif + ); + + // check that the alloc succeeded + if (ptr_out == NULL) { + return NULL; + } + + DEBUG_printf("gc_realloc: allocating new block\n"); + memcpy(ptr_out, ptr_in, n_blocks * BYTES_PER_BLOCK); + gc_free(ptr_in); + return ptr_out; } #endif // Alternative gc_realloc impl