summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien George <damien@micropython.org>2023-08-15 14:34:25 +1000
committerDamien George <damien@micropython.org>2023-08-15 16:12:54 +1000
commitfa1ea21f75601a93827d143bb9074b1f7474a953 (patch)
tree48407859e4da7aa7f84747f512f42cf9ad12193e
parent05dcb8be9957d0ed6c9694629be186a40c1a3fd9 (diff)
esp32/gccollect: Make level arg volatile to force recursive function.
Otherwise the compiler may inline the gc_collect_inner() function and/or remove the recursion, which is necessary to spill all the windowed registers to the C stack. Signed-off-by: Damien George <damien@micropython.org>
-rw-r--r--ports/esp32/gccollect.c23
1 files changed, 9 insertions, 14 deletions
diff --git a/ports/esp32/gccollect.c b/ports/esp32/gccollect.c
index e16e8028a..4b6dd8ab6 100644
--- a/ports/esp32/gccollect.c
+++ b/ports/esp32/gccollect.c
@@ -39,30 +39,25 @@
#include "xtensa/hal.h"
-static void gc_collect_inner(int level) {
+// The level argument must be volatile to force the compiler to emit code that
+// will call this function recursively, to nest the C stack.
+static void gc_collect_inner(volatile unsigned int level) {
if (level < XCHAL_NUM_AREGS / 8) {
+ // Go deeper on the stack to spill more registers from the register window.
gc_collect_inner(level + 1);
- if (level != 0) {
- return;
- }
- }
-
- if (level == XCHAL_NUM_AREGS / 8) {
- // get the sp
+ } else {
+ // Deep enough so that all registers are on the C stack, now trace the stack.
volatile uint32_t sp = (uint32_t)esp_cpu_get_sp();
gc_collect_root((void **)sp, ((mp_uint_t)MP_STATE_THREAD(stack_top) - sp) / sizeof(uint32_t));
- return;
}
-
- // trace root pointers from any threads
- #if MICROPY_PY_THREAD
- mp_thread_gc_others();
- #endif
}
void gc_collect(void) {
gc_collect_start();
gc_collect_inner(0);
+ #if MICROPY_PY_THREAD
+ mp_thread_gc_others();
+ #endif
gc_collect_end();
}