py/gc: Add new MICROPY_GC_SPLIT_HEAP_AUTO "auto grow heap" mode.
When set, the split heap is automatically extended with new areas on
demand, and shrunk if a heap area becomes empty during a GC pass or soft
reset.
To save code size the size allocation for a new heap block (including
metadata) is estimated at 103% of the failed allocation, rather than
working from the more complex algorithm in gc_try_add_heap(). This appears
to work well except in the extreme limit case when almost all RAM is
exhausted (~last few hundred bytes). However in this case some allocation
is likely to fail soon anyhow.
Currently there is no API to manually add a block of a given size to the
heap, although that could easily be added if necessary.
This work was funded through GitHub Sponsors.
Signed-off-by: Angus Gratton <angus@redyak.com.au>
diff --git a/py/mpconfig.h b/py/mpconfig.h
index 4a15205..de4a892 100644
--- a/py/mpconfig.h
+++ b/py/mpconfig.h
@@ -616,6 +616,11 @@
#define MICROPY_GC_SPLIT_HEAP (0)
#endif
+// Whether regions should be added/removed from the split heap as needed.
+#ifndef MICROPY_GC_SPLIT_HEAP_AUTO
+#define MICROPY_GC_SPLIT_HEAP_AUTO (0)
+#endif
+
// Hook to run code during time consuming garbage collector operations
// *i* is the loop index variable (e.g. can be used to run every x loops)
#ifndef MICROPY_GC_HOOK_LOOP
@@ -1896,6 +1901,16 @@
#define MP_PLAT_FREE_EXEC(ptr, size) m_del(byte, ptr, size)
#endif
+// Allocating new heap area at runtime requires port to be able to allocate from system heap
+#if MICROPY_GC_SPLIT_HEAP_AUTO
+#ifndef MP_PLAT_ALLOC_HEAP
+#define MP_PLAT_ALLOC_HEAP(size) malloc(size)
+#endif
+#ifndef MP_PLAT_FREE_HEAP
+#define MP_PLAT_FREE_HEAP(ptr) free(ptr)
+#endif
+#endif
+
// This macro is used to do all output (except when MICROPY_PY_IO is defined)
#ifndef MP_PLAT_PRINT_STRN
#define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len)