py, gc: Further simplify coding-style of gc_realloc.

No logic changes, just coding style to make it easy to read.
This commit is contained in:
Damien George 2014-04-20 18:16:25 +01:00
parent 5f6a25fc50
commit dde739d364
1 changed files with 76 additions and 63 deletions

139
py/gc.c
View File

@ -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