py/gc: Move away from using mp_uint_t, instead use uintptr_t and size_t.

The GC works with concrete pointers and so the types should reflect this.
This commit is contained in:
Damien George 2015-11-27 13:07:48 +00:00
parent 254cfa6c31
commit 94fe6e523d
3 changed files with 47 additions and 47 deletions

70
py/gc.c
View File

@ -79,8 +79,8 @@
#define ATB_HEAD_TO_MARK(block) do { MP_STATE_MEM(gc_alloc_table_start)[(block) / BLOCKS_PER_ATB] |= (AT_MARK << BLOCK_SHIFT(block)); } while (0) #define ATB_HEAD_TO_MARK(block) do { MP_STATE_MEM(gc_alloc_table_start)[(block) / BLOCKS_PER_ATB] |= (AT_MARK << BLOCK_SHIFT(block)); } while (0)
#define ATB_MARK_TO_HEAD(block) do { MP_STATE_MEM(gc_alloc_table_start)[(block) / BLOCKS_PER_ATB] &= (~(AT_TAIL << BLOCK_SHIFT(block))); } while (0) #define ATB_MARK_TO_HEAD(block) do { MP_STATE_MEM(gc_alloc_table_start)[(block) / BLOCKS_PER_ATB] &= (~(AT_TAIL << BLOCK_SHIFT(block))); } while (0)
#define BLOCK_FROM_PTR(ptr) (((ptr) - (mp_uint_t)MP_STATE_MEM(gc_pool_start)) / BYTES_PER_BLOCK) #define BLOCK_FROM_PTR(ptr) (((byte*)(ptr) - MP_STATE_MEM(gc_pool_start)) / BYTES_PER_BLOCK)
#define PTR_FROM_BLOCK(block) (((block) * BYTES_PER_BLOCK + (mp_uint_t)MP_STATE_MEM(gc_pool_start))) #define PTR_FROM_BLOCK(block) (((block) * BYTES_PER_BLOCK + (uintptr_t)MP_STATE_MEM(gc_pool_start)))
#define ATB_FROM_BLOCK(bl) ((bl) / BLOCKS_PER_ATB) #define ATB_FROM_BLOCK(bl) ((bl) / BLOCKS_PER_ATB)
#if MICROPY_ENABLE_FINALISER #if MICROPY_ENABLE_FINALISER
@ -97,7 +97,7 @@
// TODO waste less memory; currently requires that all entries in alloc_table have a corresponding block in pool // TODO waste less memory; currently requires that all entries in alloc_table have a corresponding block in pool
void gc_init(void *start, void *end) { void gc_init(void *start, void *end) {
// align end pointer on block boundary // align end pointer on block boundary
end = (void*)((mp_uint_t)end & (~(BYTES_PER_BLOCK - 1))); end = (void*)((uintptr_t)end & (~(BYTES_PER_BLOCK - 1)));
DEBUG_printf("Initializing GC heap: %p..%p = " UINT_FMT " bytes\n", start, end, (byte*)end - (byte*)start); DEBUG_printf("Initializing GC heap: %p..%p = " UINT_FMT " bytes\n", start, end, (byte*)end - (byte*)start);
// calculate parameters for GC (T=total, A=alloc table, F=finaliser table, P=pool; all in bytes): // calculate parameters for GC (T=total, A=alloc table, F=finaliser table, P=pool; all in bytes):
@ -120,11 +120,11 @@ void gc_init(void *start, void *end) {
#endif #endif
mp_uint_t gc_pool_block_len = MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB; mp_uint_t gc_pool_block_len = MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB;
MP_STATE_MEM(gc_pool_start) = (mp_uint_t*)((byte*)end - gc_pool_block_len * BYTES_PER_BLOCK); MP_STATE_MEM(gc_pool_start) = (byte*)end - gc_pool_block_len * BYTES_PER_BLOCK;
MP_STATE_MEM(gc_pool_end) = (mp_uint_t*)end; MP_STATE_MEM(gc_pool_end) = end;
#if MICROPY_ENABLE_FINALISER #if MICROPY_ENABLE_FINALISER
assert((byte*)MP_STATE_MEM(gc_pool_start) >= MP_STATE_MEM(gc_finaliser_table_start) + gc_finaliser_table_byte_len); assert(MP_STATE_MEM(gc_pool_start) >= MP_STATE_MEM(gc_finaliser_table_start) + gc_finaliser_table_byte_len);
#endif #endif
// clear ATBs // clear ATBs
@ -164,12 +164,14 @@ bool gc_is_locked(void) {
return MP_STATE_MEM(gc_lock_depth) != 0; return MP_STATE_MEM(gc_lock_depth) != 0;
} }
// ptr should be of type void*
#define VERIFY_PTR(ptr) ( \ #define VERIFY_PTR(ptr) ( \
(ptr & (BYTES_PER_BLOCK - 1)) == 0 /* must be aligned on a block */ \ ((uintptr_t)(ptr) & (BYTES_PER_BLOCK - 1)) == 0 /* must be aligned on a block */ \
&& ptr >= (mp_uint_t)MP_STATE_MEM(gc_pool_start) /* must be above start of pool */ \ && ptr >= (void*)MP_STATE_MEM(gc_pool_start) /* must be above start of pool */ \
&& ptr < (mp_uint_t)MP_STATE_MEM(gc_pool_end) /* must be below end of pool */ \ && ptr < (void*)MP_STATE_MEM(gc_pool_end) /* must be below end of pool */ \
) )
// ptr should be of type void*
#define VERIFY_MARK_AND_PUSH(ptr) \ #define VERIFY_MARK_AND_PUSH(ptr) \
do { \ do { \
if (VERIFY_PTR(ptr)) { \ if (VERIFY_PTR(ptr)) { \
@ -189,7 +191,7 @@ bool gc_is_locked(void) {
STATIC void gc_drain_stack(void) { STATIC void gc_drain_stack(void) {
while (MP_STATE_MEM(gc_sp) > MP_STATE_MEM(gc_stack)) { while (MP_STATE_MEM(gc_sp) > MP_STATE_MEM(gc_stack)) {
// pop the next block off the stack // pop the next block off the stack
mp_uint_t block = *--MP_STATE_MEM(gc_sp); size_t block = *--MP_STATE_MEM(gc_sp);
// work out number of consecutive blocks in the chain starting with this one // work out number of consecutive blocks in the chain starting with this one
mp_uint_t n_blocks = 0; mp_uint_t n_blocks = 0;
@ -198,9 +200,10 @@ STATIC void gc_drain_stack(void) {
} while (ATB_GET_KIND(block + n_blocks) == AT_TAIL); } while (ATB_GET_KIND(block + n_blocks) == AT_TAIL);
// check this block's children // check this block's children
mp_uint_t *scan = (mp_uint_t*)PTR_FROM_BLOCK(block); mp_obj_t *scan = (mp_obj_t*)PTR_FROM_BLOCK(block);
for (mp_uint_t i = n_blocks * WORDS_PER_BLOCK; i > 0; i--, scan++) { for (mp_uint_t i = n_blocks * WORDS_PER_BLOCK; i > 0; i--, scan++) {
mp_uint_t ptr2 = *scan; mp_obj_t obj = *scan;
void *ptr2 = (void*)obj;
VERIFY_MARK_AND_PUSH(ptr2); VERIFY_MARK_AND_PUSH(ptr2);
} }
} }
@ -276,12 +279,12 @@ void gc_collect_start(void) {
// correctly in the mp_state_ctx structure. We scan nlr_top, dict_locals, // correctly in the mp_state_ctx structure. We scan nlr_top, dict_locals,
// dict_globals, then the root pointer section of mp_state_vm. // dict_globals, then the root pointer section of mp_state_vm.
void **ptrs = (void**)(void*)&mp_state_ctx; void **ptrs = (void**)(void*)&mp_state_ctx;
gc_collect_root(ptrs, offsetof(mp_state_ctx_t, vm.stack_top) / sizeof(mp_uint_t)); gc_collect_root(ptrs, offsetof(mp_state_ctx_t, vm.stack_top) / sizeof(void*));
} }
void gc_collect_root(void **ptrs, mp_uint_t len) { void gc_collect_root(void **ptrs, size_t len) {
for (mp_uint_t i = 0; i < len; i++) { for (size_t i = 0; i < len; i++) {
mp_uint_t ptr = (mp_uint_t)ptrs[i]; void *ptr = ptrs[i];
VERIFY_MARK_AND_PUSH(ptr); VERIFY_MARK_AND_PUSH(ptr);
gc_drain_stack(); gc_drain_stack();
} }
@ -295,7 +298,7 @@ void gc_collect_end(void) {
} }
void gc_info(gc_info_t *info) { void gc_info(gc_info_t *info) {
info->total = (MP_STATE_MEM(gc_pool_end) - MP_STATE_MEM(gc_pool_start)) * sizeof(mp_uint_t); info->total = MP_STATE_MEM(gc_pool_end) - MP_STATE_MEM(gc_pool_start);
info->used = 0; info->used = 0;
info->free = 0; info->free = 0;
info->num_1block = 0; info->num_1block = 0;
@ -339,7 +342,7 @@ void gc_info(gc_info_t *info) {
info->free *= BYTES_PER_BLOCK; info->free *= BYTES_PER_BLOCK;
} }
void *gc_alloc(mp_uint_t n_bytes, bool has_finaliser) { void *gc_alloc(size_t n_bytes, bool has_finaliser) {
mp_uint_t n_blocks = ((n_bytes + BYTES_PER_BLOCK - 1) & (~(BYTES_PER_BLOCK - 1))) / BYTES_PER_BLOCK; mp_uint_t n_blocks = ((n_bytes + BYTES_PER_BLOCK - 1) & (~(BYTES_PER_BLOCK - 1))) / BYTES_PER_BLOCK;
DEBUG_printf("gc_alloc(" UINT_FMT " bytes -> " UINT_FMT " blocks)\n", n_bytes, n_blocks); DEBUG_printf("gc_alloc(" UINT_FMT " bytes -> " UINT_FMT " blocks)\n", n_bytes, n_blocks);
@ -403,7 +406,7 @@ found:
} }
// get pointer to first block // get pointer to first block
void *ret_ptr = (void*)(MP_STATE_MEM(gc_pool_start) + start_block * WORDS_PER_BLOCK); void *ret_ptr = (void*)(MP_STATE_MEM(gc_pool_start) + start_block * BYTES_PER_BLOCK);
DEBUG_printf("gc_alloc(%p)\n", ret_ptr); DEBUG_printf("gc_alloc(%p)\n", ret_ptr);
// zero out the additional bytes of the newly allocated blocks // zero out the additional bytes of the newly allocated blocks
@ -416,7 +419,7 @@ found:
#if MICROPY_ENABLE_FINALISER #if MICROPY_ENABLE_FINALISER
if (has_finaliser) { if (has_finaliser) {
// clear type pointer in case it is never set // clear type pointer in case it is never set
((mp_obj_base_t*)ret_ptr)->type = MP_OBJ_NULL; ((mp_obj_base_t*)ret_ptr)->type = NULL;
// set mp_obj flag only if it has a finaliser // set mp_obj flag only if it has a finaliser
FTB_SET(start_block); FTB_SET(start_block);
} }
@ -443,13 +446,12 @@ void *gc_alloc_with_finaliser(mp_uint_t n_bytes) {
// force the freeing of a piece of memory // force the freeing of a piece of memory
// TODO: freeing here does not call finaliser // TODO: freeing here does not call finaliser
void gc_free(void *ptr_in) { void gc_free(void *ptr) {
if (MP_STATE_MEM(gc_lock_depth) > 0) { if (MP_STATE_MEM(gc_lock_depth) > 0) {
// TODO how to deal with this error? // TODO how to deal with this error?
return; return;
} }
mp_uint_t ptr = (mp_uint_t)ptr_in;
DEBUG_printf("gc_free(%p)\n", ptr); DEBUG_printf("gc_free(%p)\n", ptr);
if (VERIFY_PTR(ptr)) { if (VERIFY_PTR(ptr)) {
@ -475,14 +477,12 @@ void gc_free(void *ptr_in) {
} else { } else {
assert(!"bad free"); assert(!"bad free");
} }
} else if (ptr_in != NULL) { } else if (ptr != NULL) {
assert(!"bad free"); assert(!"bad free");
} }
} }
mp_uint_t gc_nbytes(const void *ptr_in) { size_t gc_nbytes(const void *ptr) {
mp_uint_t ptr = (mp_uint_t)ptr_in;
if (VERIFY_PTR(ptr)) { if (VERIFY_PTR(ptr)) {
mp_uint_t block = BLOCK_FROM_PTR(ptr); mp_uint_t block = BLOCK_FROM_PTR(ptr);
if (ATB_GET_KIND(block) == AT_HEAD) { if (ATB_GET_KIND(block) == AT_HEAD) {
@ -528,7 +528,7 @@ void *gc_realloc(void *ptr, mp_uint_t n_bytes) {
#else // Alternative gc_realloc impl #else // Alternative gc_realloc impl
void *gc_realloc(void *ptr_in, mp_uint_t n_bytes, bool allow_move) { void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) {
if (MP_STATE_MEM(gc_lock_depth) > 0) { if (MP_STATE_MEM(gc_lock_depth) > 0) {
return NULL; return NULL;
} }
@ -544,7 +544,7 @@ void *gc_realloc(void *ptr_in, mp_uint_t n_bytes, bool allow_move) {
return NULL; return NULL;
} }
mp_uint_t ptr = (mp_uint_t)ptr_in; void *ptr = ptr_in;
// sanity check the ptr // sanity check the ptr
if (!VERIFY_PTR(ptr)) { if (!VERIFY_PTR(ptr)) {
@ -730,15 +730,15 @@ void gc_dump_alloc_table(void) {
*/ */
/* this prints the uPy object type of the head block */ /* this prints the uPy object type of the head block */
case AT_HEAD: { case AT_HEAD: {
mp_uint_t *ptr = MP_STATE_MEM(gc_pool_start) + bl * WORDS_PER_BLOCK; void **ptr = (void**)(MP_STATE_MEM(gc_pool_start) + bl * BYTES_PER_BLOCK);
if (*ptr == (mp_uint_t)&mp_type_tuple) { c = 'T'; } if (*ptr == &mp_type_tuple) { c = 'T'; }
else if (*ptr == (mp_uint_t)&mp_type_list) { c = 'L'; } else if (*ptr == &mp_type_list) { c = 'L'; }
else if (*ptr == (mp_uint_t)&mp_type_dict) { c = 'D'; } else if (*ptr == &mp_type_dict) { c = 'D'; }
#if MICROPY_PY_BUILTINS_FLOAT #if MICROPY_PY_BUILTINS_FLOAT
else if (*ptr == (mp_uint_t)&mp_type_float) { c = 'F'; } else if (*ptr == &mp_type_float) { c = 'F'; }
#endif #endif
else if (*ptr == (mp_uint_t)&mp_type_fun_bc) { c = 'B'; } else if (*ptr == &mp_type_fun_bc) { c = 'B'; }
else if (*ptr == (mp_uint_t)&mp_type_module) { c = 'M'; } else if (*ptr == &mp_type_module) { c = 'M'; }
else { else {
c = 'h'; c = 'h';
#if 0 #if 0

20
py/gc.h
View File

@ -42,21 +42,21 @@ bool gc_is_locked(void);
// A given port must implement gc_collect by using the other collect functions. // A given port must implement gc_collect by using the other collect functions.
void gc_collect(void); void gc_collect(void);
void gc_collect_start(void); void gc_collect_start(void);
void gc_collect_root(void **ptrs, mp_uint_t len); void gc_collect_root(void **ptrs, size_t len);
void gc_collect_end(void); void gc_collect_end(void);
void *gc_alloc(mp_uint_t n_bytes, bool has_finaliser); void *gc_alloc(size_t n_bytes, bool has_finaliser);
void gc_free(void *ptr); // does not call finaliser void gc_free(void *ptr); // does not call finaliser
mp_uint_t gc_nbytes(const void *ptr); size_t gc_nbytes(const void *ptr);
void *gc_realloc(void *ptr, mp_uint_t n_bytes, bool allow_move); void *gc_realloc(void *ptr, size_t n_bytes, bool allow_move);
typedef struct _gc_info_t { typedef struct _gc_info_t {
mp_uint_t total; size_t total;
mp_uint_t used; size_t used;
mp_uint_t free; size_t free;
mp_uint_t num_1block; size_t num_1block;
mp_uint_t num_2block; size_t num_2block;
mp_uint_t max_block; size_t max_block;
} gc_info_t; } gc_info_t;
void gc_info(gc_info_t *info); void gc_info(gc_info_t *info);

View File

@ -52,8 +52,8 @@ typedef struct _mp_state_mem_t {
#if MICROPY_ENABLE_FINALISER #if MICROPY_ENABLE_FINALISER
byte *gc_finaliser_table_start; byte *gc_finaliser_table_start;
#endif #endif
mp_uint_t *gc_pool_start; byte *gc_pool_start;
mp_uint_t *gc_pool_end; byte *gc_pool_end;
int gc_stack_overflow; int gc_stack_overflow;
mp_uint_t gc_stack[MICROPY_ALLOC_GC_STACK_SIZE]; mp_uint_t gc_stack[MICROPY_ALLOC_GC_STACK_SIZE];