summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--py/gc.c20
1 files changed, 17 insertions, 3 deletions
diff --git a/py/gc.c b/py/gc.c
index 80e5f8036..b6969dfd4 100644
--- a/py/gc.c
+++ b/py/gc.c
@@ -282,14 +282,28 @@ STATIC bool gc_try_add_heap(size_t failed_alloc) {
// - If the new heap won't fit in the available free space, add the largest
// new heap that will fit (this may lead to failed system heap allocations
// elsewhere, but some allocation will likely fail in this circumstance!)
- size_t total_heap = 0;
+
+ // Compute total number of blocks in the current heap.
+ size_t total_blocks = 0;
for (mp_state_mem_area_t *area = &MP_STATE_MEM(area);
area != NULL;
area = NEXT_AREA(area)) {
- total_heap += area->gc_pool_end - area->gc_alloc_table_start;
- total_heap += ALLOC_TABLE_GAP_BYTE + sizeof(mp_state_mem_area_t);
+ total_blocks += area->gc_alloc_table_byte_len * BLOCKS_PER_ATB;
}
+ // Compute bytes needed to build a heap with total_blocks blocks.
+ size_t total_heap =
+ total_blocks / BLOCKS_PER_ATB
+ #if MICROPY_ENABLE_FINALISER
+ + total_blocks / BLOCKS_PER_FTB
+ #endif
+ + total_blocks * BYTES_PER_BLOCK
+ + ALLOC_TABLE_GAP_BYTE
+ + sizeof(mp_state_mem_area_t);
+
+ // Round up size to the nearest multiple of BYTES_PER_BLOCK.
+ total_heap = (total_heap + BYTES_PER_BLOCK - 1) & (~(BYTES_PER_BLOCK - 1));
+
DEBUG_printf("total_heap " UINT_FMT " bytes\n", total_heap);
size_t to_alloc = MIN(avail, MAX(total_heap, needed));