From 252e16ef8e4c2f4ae7401f69aa572b0f109e23f1 Mon Sep 17 00:00:00 2001 From: Adeel Mujahid <3840695+am11@users.noreply.github.com> Date: Wed, 23 Sep 2026 12:50:04 +0300 Subject: [PATCH 1/2] Honor stack_limit in NativeAOT PromoteCarefully --- src/coreclr/nativeaot/Runtime/GcEnum.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/coreclr/nativeaot/Runtime/GcEnum.cpp b/src/coreclr/nativeaot/Runtime/GcEnum.cpp index a3ad32eba02023..f8c39cab0d52dd 100644 --- a/src/coreclr/nativeaot/Runtime/GcEnum.cpp +++ b/src/coreclr/nativeaot/Runtime/GcEnum.cpp @@ -28,7 +28,8 @@ static void PromoteCarefully(PTR_PTR_Object obj, uint32_t flags, ScanFunc* fnGcE // If the object reference points into the stack, we // must not promote it, the GC cannot handle these. - if (pSc->thread_under_crawl->IsWithinStackBounds(*obj)) + // Only the part above stack_limit is live stack; the recorded bounds can span other mappings (e.g. musl main thread under QEMU). + if (pSc->thread_under_crawl->IsWithinStackBounds(*obj) && ((uintptr_t)*obj >= pSc->stack_limit)) return; fnGcEnumRef(obj, pSc, flags); From 9bfa6edb89151703423b823775a728428188dfaf Mon Sep 17 00:00:00 2001 From: Adeel Mujahid <3840695+am11@users.noreply.github.com> Date: Wed, 23 Sep 2026 17:33:58 +0300 Subject: [PATCH 2/2] Sync comment with coreclr --- src/coreclr/nativeaot/Runtime/GcEnum.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime/GcEnum.cpp b/src/coreclr/nativeaot/Runtime/GcEnum.cpp index f8c39cab0d52dd..e6b09340681417 100644 --- a/src/coreclr/nativeaot/Runtime/GcEnum.cpp +++ b/src/coreclr/nativeaot/Runtime/GcEnum.cpp @@ -26,9 +26,13 @@ static void PromoteCarefully(PTR_PTR_Object obj, uint32_t flags, ScanFunc* fnGcE // assert(flags & GC_CALL_INTERIOR); - // If the object reference points into the stack, we - // must not promote it, the GC cannot handle these. - // Only the part above stack_limit is live stack; the recorded bounds can span other mappings (e.g. musl main thread under QEMU). + // Note that the base is at a higher address than the limit, since the stack + // grows downwards. + // To check whether the object is in the stack or not, we also need to check the sc->stack_limit. + // The reason is that on Unix, the stack size can be unlimited. In such case, the system can + // shrink the current reserved stack space. That causes the real limit of the stack to move up and + // the range can be reused for other purposes. But the sc->stack_limit is stable during the scan. + // Even on Windows, we care just about the stack above the stack_limit. if (pSc->thread_under_crawl->IsWithinStackBounds(*obj) && ((uintptr_t)*obj >= pSc->stack_limit)) return;