
The only architecture that actually needs special support for scanning the stack is WebAssembly. All others allow raw access to the stack with a small bit of assembly. Therefore, don't manually keep track of all these objects on the stack manually and instead just use conservative stack scanning. This results in a massive code size decrease in the affected targets (only tested linux/amd64 for code size) - sometimes around 33%. It also allows for future improvements such as using proper stackful goroutines.
40 строки
1,1 КиБ
Go
40 строки
1,1 КиБ
Go
// +build gc.conservative gc.extalloc
|
|
// +build !wasm
|
|
|
|
package runtime
|
|
|
|
import "internal/task"
|
|
|
|
// markStack marks all root pointers found on the stack.
|
|
//
|
|
// This implementation is conservative and relies on the stack top (provided by
|
|
// the linker) and getting the current stack pointer from a register. Also, it
|
|
// assumes a descending stack. Thus, it is not very portable.
|
|
func markStack() {
|
|
// Scan the current stack, and all current registers.
|
|
scanCurrentStack()
|
|
|
|
if !task.OnSystemStack() {
|
|
// Mark system stack.
|
|
markRoots(getSystemStackPointer(), stackTop)
|
|
}
|
|
}
|
|
|
|
//go:export tinygo_scanCurrentStack
|
|
func scanCurrentStack()
|
|
|
|
//go:export tinygo_scanstack
|
|
func scanstack(sp uintptr) {
|
|
// Mark current stack.
|
|
// This function is called by scanCurrentStack, after pushing all registers onto the stack.
|
|
// Callee-saved registers have been pushed onto stack by tinygo_localscan, so this will scan them too.
|
|
if task.OnSystemStack() {
|
|
// This is the system stack.
|
|
// Scan all words on the stack.
|
|
markRoots(sp, stackTop)
|
|
} else {
|
|
// This is a goroutine stack.
|
|
// It is an allocation, so scan it as if it were a value in a global.
|
|
markRoot(0, sp)
|
|
}
|
|
}
|