From 56bc4a6a3568414f4d868e71665ee7d689edaeef Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Thu, 17 Nov 2022 14:06:37 +0100 Subject: [PATCH] wasm: fix scanning of the stack LLVM wasn't aware that runtime.stackChainStart must be kept live and can't be optimized away. With this hack, it is forced to consider stackChainStart live at the time of the stack scan. This fixes the corruption in https://github.com/tinygo-org/tinygo/issues/3277 --- src/runtime/gc_stack_portable.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/runtime/gc_stack_portable.go b/src/runtime/gc_stack_portable.go index d4a191f05d..e6ff9ce702 100644 --- a/src/runtime/gc_stack_portable.go +++ b/src/runtime/gc_stack_portable.go @@ -6,6 +6,7 @@ package runtime import ( "internal/task" + "runtime/volatile" "unsafe" ) @@ -39,6 +40,13 @@ type stackChainObject struct { // stackChainStart. Luckily we don't need to scan these, as these globals are // stored on the goroutine stack and are therefore already getting scanned. func markStack() { + // Hack to force LLVM to consider stackChainStart to be live. + // Without this hack, loads and stores may be considered dead and objects on + // the stack might not be correctly tracked. With this volatile load, LLVM + // is forced to consider stackChainStart (and everything it points to) as + // live. + volatile.LoadUint32((*uint32)(unsafe.Pointer(&stackChainStart))) + if task.OnSystemStack() { markRoots(getCurrentStackPointer(), stackTop) }