diff --git a/src/runtime/gc_conservative.go b/src/runtime/gc_conservative.go index 955b6d99..e0e13bc2 100644 --- a/src/runtime/gc_conservative.go +++ b/src/runtime/gc_conservative.go @@ -430,8 +430,18 @@ func markRoots(start, end uintptr) { if start >= end { runtimePanic("gc: unexpected range to mark") } + if start%unsafe.Alignof(start) != 0 { + runtimePanic("gc: unaligned start pointer") + } + if end%unsafe.Alignof(end) != 0 { + runtimePanic("gc: unaligned end pointer") + } } + // Reduce the end bound to avoid reading too far on platforms where pointer alignment is smaller than pointer size. + // If the size of the range is 0, then end will be slightly below start after this. + end -= unsafe.Sizeof(end) - unsafe.Alignof(end) + for addr := start; addr < end; addr += unsafe.Alignof(addr) { root := *(*uintptr)(unsafe.Pointer(addr)) markRoot(addr, root) diff --git a/src/runtime/gc_globals_conservative.go b/src/runtime/gc_globals_conservative.go index 56476551..b4d19470 100644 --- a/src/runtime/gc_globals_conservative.go +++ b/src/runtime/gc_globals_conservative.go @@ -1,12 +1,24 @@ +//go:build (gc.conservative || gc.extalloc) && (baremetal || tinygo.wasm) // +build gc.conservative gc.extalloc // +build baremetal tinygo.wasm package runtime +import "unsafe" + // markGlobals marks all globals, which are reachable by definition. // // This implementation marks all globals conservatively and assumes it can use // linker-defined symbols for the start and end of the .data section. func markGlobals() { - markRoots(globalsStart, globalsEnd) + end := globalsEnd + if GOARCH == "wasm" { + // This is a workaround for a bug in wasm-ld: wasm-ld doesn't always + // align __heap_base and when this memory is shared through an API, it + // might result in unaligned memory. For details, see: + // https://reviews.llvm.org/D106499 + // It should be removed once we switch to LLVM 13, where this is fixed. + end = end &^ (unsafe.Alignof(end) - 1) + } + markRoots(globalsStart, end) }