summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ports/unix/gccollect.c11
1 files changed, 8 insertions, 3 deletions
diff --git a/ports/unix/gccollect.c b/ports/unix/gccollect.c
index 02f6fc91a..ddc2d92c3 100644
--- a/ports/unix/gccollect.c
+++ b/ports/unix/gccollect.c
@@ -149,9 +149,14 @@ STATIC void gc_helper_get_regs(regs_t arr) {
#endif // MICROPY_GCREGS_SETJMP
// this function is used by mpthreadport.c
-void gc_collect_regs_and_stack(void);
-
-void gc_collect_regs_and_stack(void) {
+MP_NOINLINE void gc_collect_regs_and_stack(void);
+
+// Explicitly mark this as noinline to make sure the regs variable
+// is effectively at the top of the stack: otherwise, in builds where
+// LTO is enabled and a lot of inlining takes place we risk a stack
+// layout where regs is lower on the stack than pointers which have
+// just been allocated but not yet marked, and get incorrectly sweeped.
+MP_NOINLINE void gc_collect_regs_and_stack(void) {
regs_t regs;
gc_helper_get_regs(regs);
// GC stack (and regs because we captured them)