mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-09-10 14:39:31 +00:00
02021b5853
C malloc storage has explicit lifetime: it must remain allocated until free even when no GC-visible pointer references it. Treating it as an ordinary NoPtrs allocation breaks bare-metal C object graphs, while conservatively scanning arbitrary C bytes creates false Go roots. Add allocManual/freeManual so collectors can represent pointer-free, explicitly managed storage. Block GC keeps these objects permanently marked and releases their blocks on free; Boehm uses atomic uncollectable allocations; leaking and custom collectors provide equivalent behavior. Wasm keeps its allocation map only for validation and sizes, and WASIp2 realloc now copies min(oldSize, newSize). Bump the Boehm library cache version because enabling atomic uncollectable allocations changes its compiled flags and exported API. Also handle zero-size and overflowing allocations, serialize allocation registries, reject Go finalizers on manual storage, and add CGo regressions for C pointer graphs, hidden until-free allocations, repeated free/reuse, and allocation edge cases.
93 lines
2.9 KiB
Go
93 lines
2.9 KiB
Go
package builder
|
|
|
|
// The well-known conservative Boehm-Demers-Weiser GC.
|
|
// This file provides a way to compile this GC for use with TinyGo.
|
|
|
|
import (
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/tinygo-org/tinygo/goenv"
|
|
)
|
|
|
|
var BoehmGC = Library{
|
|
name: "bdwgc",
|
|
cflags: func(target, headerPath string) []string {
|
|
libdir := filepath.Join(goenv.Get("TINYGOROOT"), "lib/bdwgc")
|
|
flags := []string{
|
|
// use a modern environment
|
|
"-DUSE_MMAP", // mmap is available
|
|
"-DUSE_MUNMAP", // return memory to the OS using munmap
|
|
"-DGC_BUILTIN_ATOMIC", // use compiler intrinsics for atomic operations
|
|
"-DNO_EXECUTE_PERMISSION", // don't make the heap executable
|
|
|
|
// specific flags for TinyGo
|
|
"-DALL_INTERIOR_POINTERS", // scan interior pointers (needed for Go)
|
|
"-DIGNORE_DYNAMIC_LOADING", // we don't support dynamic loading at the moment
|
|
"-DNO_GETCONTEXT", // musl doesn't support getcontext()
|
|
"-DGC_DISABLE_INCREMENTAL", // don't mess with SIGSEGV and such
|
|
|
|
// Use a minimal environment.
|
|
"-DNO_MSGBOX_ON_ERROR", // don't call MessageBoxA on Windows
|
|
"-DDONT_USE_ATEXIT",
|
|
"-DNO_GETENV", // smaller binary, more predictable configuration
|
|
"-DNO_CLOCK", // don't use system clock
|
|
"-DNO_DEBUGGING", // reduce code size
|
|
"-DGC_NO_FINALIZATION", // finalization is not used at the moment
|
|
"-DGC_ATOMIC_UNCOLLECTABLE", // pointer-free storage retained until GC_free
|
|
|
|
// Special flag to work around the lack of __data_start in ld.lld.
|
|
// TODO: try to fix this in LLVM/lld directly so we don't have to
|
|
// work around it anymore.
|
|
"-DGC_DONT_REGISTER_MAIN_STATIC_DATA",
|
|
|
|
// Do not scan the stack. We have our own mechanism to do this.
|
|
"-DSTACK_NOT_SCANNED",
|
|
"-DNO_PROC_STAT", // we scan the stack manually (don't read /proc/self/stat on Linux)
|
|
"-DSTACKBOTTOM=0", // dummy value, we scan the stack manually
|
|
|
|
// Assertions can be enabled while debugging GC issues.
|
|
//"-DGC_ASSERTIONS",
|
|
|
|
// We use our own way of dealing with threads (that is a bit hacky).
|
|
// See src/runtime/gc_boehm.go.
|
|
//"-DGC_THREADS",
|
|
//"-DTHREAD_LOCAL_ALLOC",
|
|
|
|
"-I" + libdir + "/include",
|
|
}
|
|
return flags
|
|
},
|
|
needsLibc: true,
|
|
sourceDir: func() string {
|
|
return filepath.Join(goenv.Get("TINYGOROOT"), "lib/bdwgc")
|
|
},
|
|
librarySources: func(target string, _ bool) ([]string, error) {
|
|
sources := []string{
|
|
"allchblk.c",
|
|
"alloc.c",
|
|
"blacklst.c",
|
|
"dbg_mlc.c",
|
|
"dyn_load.c",
|
|
"headers.c",
|
|
"mach_dep.c",
|
|
"malloc.c",
|
|
"mark.c",
|
|
"mark_rts.c",
|
|
"misc.c",
|
|
"new_hblk.c",
|
|
"os_dep.c",
|
|
"reclaim.c",
|
|
}
|
|
if strings.Split(target, "-")[2] == "windows" {
|
|
// Due to how the linker on Windows works (that doesn't allow
|
|
// undefined functions), we need to include these extra files.
|
|
sources = append(sources,
|
|
"mallocx.c",
|
|
"ptr_chck.c",
|
|
)
|
|
}
|
|
return sources, nil
|
|
},
|
|
}
|