mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-03 10:37:46 +00:00
8135be4e90
TODO: Remove the go.mod/go.sum in internal/tools once doing so doesn't break CI (e.g. once we drop support for go 1.19) * builder/cc1as.h: fix typo found by 'make spell' * GNUmakefile: remove exception for inbetween, fix instance now found by 'make spell' * GNUmakefile: remove exception for programmmer, fix instance now found by 'make spell' * go.mod: use updated misspell. GNUmakefile: add spellfix target, use it. * ignore directories properly when invoking spellchecker. * make spell: give internal/tools its own go.mod, as misspell requires newer go * make lint: depend on tools and run the installed revive (which was perhaps implied by the change that added revive to internal/tools, but not required in GNUmakefile until we gave internal/tools its own temporary go.mod) * .github: now that 'make spell' works well, run it from CI * GNUmakefile: make spell now aborts if it finds misspelt words, so what it finds doesn't get lost in CI logs * GNUmakefile: tools: avoid -C option on go generate to make test-llvm15-go119 circleci job happy, see https://cs.opensource.google/go/go/+/2af48cbb7d85e5fdc635e75b99f949010c607786 * internal/tools/go.mod: fix format of go version to leave out patchlevel, else go complains.
63 lines
2.3 KiB
Go
63 lines
2.3 KiB
Go
//go:build (gc.conservative || gc.custom || gc.precise) && tinygo.wasm
|
|
|
|
package runtime
|
|
|
|
import (
|
|
"internal/task"
|
|
"runtime/volatile"
|
|
"unsafe"
|
|
)
|
|
|
|
//go:extern runtime.stackChainStart
|
|
var stackChainStart *stackChainObject
|
|
|
|
type stackChainObject struct {
|
|
parent *stackChainObject
|
|
numSlots uintptr
|
|
}
|
|
|
|
// markStack marks all root pointers found on the stack.
|
|
//
|
|
// - Goroutine stacks are heap allocated and always reachable in some way
|
|
// (for example through internal/task.currentTask) so they will always be
|
|
// scanned.
|
|
// - The system stack (aka startup stack) is not heap allocated, so even
|
|
// though it may be referenced it will not be scanned by default.
|
|
//
|
|
// Therefore, we only need to scan the system stack.
|
|
// It is relatively easy to scan the system stack while we're on it: we can
|
|
// simply read __stack_pointer and __global_base and scan the area in between.
|
|
// Unfortunately, it's hard to get the system stack pointer while we're on a
|
|
// goroutine stack. But when we're on a goroutine stack, the system stack is in
|
|
// the scheduler which means there shouldn't be anything on the system stack
|
|
// anyway.
|
|
// ...I hope this assumption holds, otherwise we will need to store the system
|
|
// stack in a global or something.
|
|
//
|
|
// The compiler also inserts code to store all globals in a chain via
|
|
// 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)
|
|
}
|
|
}
|
|
|
|
// trackPointer is a stub function call inserted by the compiler during IR
|
|
// construction. Calls to it are later replaced with regular stack bookkeeping
|
|
// code.
|
|
func trackPointer(ptr, alloca unsafe.Pointer)
|
|
|
|
// swapStackChain swaps the stack chain.
|
|
// This is called from internal/task when switching goroutines.
|
|
func swapStackChain(dst **stackChainObject) {
|
|
*dst, stackChainStart = stackChainStart, *dst
|
|
}
|