From 7da3766d1732dc8ebdb8488b49483828873d10ae Mon Sep 17 00:00:00 2001 From: Edd Barrett Date: Tue, 31 Mar 2026 14:41:54 +0100 Subject: [PATCH] Work around alloca(3) in `fun_bc_call()`. alloca(3) causes the frame to have dynamic size, which in-turn breaks stackmaps. For this reason, functions which use alloca(3) are `yk_outline`d by ykllvm. micropython avoids lots of heap allocation by storing small code states on the stack with alloca(3). This means we can't trace. This change nullifies the optimisation, so we always allocate code states on te GC heap. If you were to add `yk_unroll_safe` and `yk_indirect_inline` to `fun_bc_call()`, then it would not be `yk_outline` and we'd have a full definition in the AOR IR. --- py/objfun.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/py/objfun.c b/py/objfun.c index 5feb4cd2196ce..67ce86ac49acd 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -27,6 +27,9 @@ #include #include +#ifdef USE_YK +#include +#endif #include "py/emitglue.h" #include "py/objcode.h" @@ -270,7 +273,18 @@ static mp_obj_t fun_bc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const #if MICROPY_ENABLE_PYSTACK code_state = mp_pystack_alloc(offsetof(mp_code_state_t, state) + state_size); #else +#ifdef USE_YK + // Avoid alloca(3) when using yk. + // + // Fucntions that use alloca(3) cannot be traced because stackmaps don't + // work on dynamically-sized frames. + // + // Instead of storing "small" code states on the stack (using alloca), we + // therefore store *all* code states on the GC heap. + { +#else if (state_size > VM_MAX_STATE_ON_STACK) { +#endif code_state = m_new_obj_var_maybe(mp_code_state_t, state, byte, state_size); #if MICROPY_DEBUG_VM_STACK_OVERFLOW if (code_state != NULL) { @@ -279,11 +293,15 @@ static mp_obj_t fun_bc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const #endif } if (code_state == NULL) { +#ifdef USE_YK + abort(); // we must have heap allocated +#else code_state = alloca(offsetof(mp_code_state_t, state) + state_size); #if MICROPY_DEBUG_VM_STACK_OVERFLOW memset(code_state->state, 0, state_size); #endif state_size = 0; // indicate that we allocated using alloca +#endif } #endif