mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-05 11:37:46 +00:00
runtime (gc): correct scan bounds
This fixes 2 bugs in the GC scan bounds: 1. On AVR, the GC could sometimes read one byte past the end of a block due to the difference between pointer size and alignment. 2. On WASM, the linker does not properly align the marker for the end of the globals section. A manual alignment operation has been added to markGlobals to work around this.
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user