diff --git a/components/micropython/vendor/py/gc.c b/components/micropython/vendor/py/gc.c index ba5c569d50f861f84e0f2e3726c93311a406aa36..1430ca32818282a3eb5ace74f081ff6123c70151 100644 --- a/components/micropython/vendor/py/gc.c +++ b/components/micropython/vendor/py/gc.c @@ -158,6 +158,7 @@ STATIC void gc_setup_area(mp_state_mem_area_t *area, void *start, void *end) { #endif area->gc_last_free_atb_index = 0; + area->gc_last_used_block = 0; #if MICROPY_GC_SPLIT_HEAP area->next = NULL; @@ -380,7 +381,14 @@ STATIC void gc_sweep(void) { // free unmarked heads and their tails int free_tail = 0; for (mp_state_mem_area_t *area = &MP_STATE_MEM(area); area != NULL; area = NEXT_AREA(area)) { - for (size_t block = 0; block < area->gc_alloc_table_byte_len * BLOCKS_PER_ATB; block++) { + size_t end_block = area->gc_alloc_table_byte_len * BLOCKS_PER_ATB; + if (area->gc_last_used_block < end_block) { + end_block = area->gc_last_used_block + 1; + } + + size_t last_used_block = 0; + + for (size_t block = 0; block < end_block; block++) { MICROPY_GC_HOOK_LOOP switch (ATB_GET_KIND(area, block)) { case AT_HEAD: @@ -420,15 +428,20 @@ STATIC void gc_sweep(void) { #if CLEAR_ON_SWEEP memset((void *)PTR_FROM_BLOCK(area, block), 0, BYTES_PER_BLOCK); #endif + } else { + last_used_block = block; } break; case AT_MARK: ATB_MARK_TO_HEAD(area, block); free_tail = 0; + last_used_block = block; break; } } + + area->gc_last_used_block = last_used_block; } } @@ -680,6 +693,8 @@ found: area->gc_last_free_atb_index = (i + 1) / BLOCKS_PER_ATB; } + area->gc_last_used_block = MAX(area->gc_last_used_block, end_block); + // mark first block as used head ATB_FREE_TO_HEAD(area, start_block); @@ -969,11 +984,14 @@ void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) { // check if we can expand in place if (new_blocks <= n_blocks + n_free) { // mark few more blocks as used tail - for (size_t bl = block + n_blocks; bl < block + new_blocks; bl++) { + size_t end_block = block + new_blocks; + for (size_t bl = block + n_blocks; bl < end_block; bl++) { assert(ATB_GET_KIND(area, bl) == AT_FREE); ATB_FREE_TO_TAIL(area, bl); } + area->gc_last_used_block = MAX(area->gc_last_used_block, end_block); + GC_EXIT(); #if MICROPY_GC_CONSERVATIVE_CLEAR diff --git a/components/micropython/vendor/py/mpstate.h b/components/micropython/vendor/py/mpstate.h index f6b911af5658c7db1438b92b70fcaad7b6182947..11caeba05520b0d4d21bdb241140194ceaedb2cf 100644 --- a/components/micropython/vendor/py/mpstate.h +++ b/components/micropython/vendor/py/mpstate.h @@ -87,6 +87,7 @@ typedef struct _mp_state_mem_area_t { byte *gc_pool_end; size_t gc_last_free_atb_index; + size_t gc_last_used_block; // The block ID of the highest block allocated in the area } mp_state_mem_area_t; // This structure hold information about the memory allocation system.