
This implements the block-based GC as a partially precise GC. This means that for most heap allocations it is known which words contain a pointer and which don't. This should in theory make the GC faster (because it can skip non-pointer object) and have fewer false positives in a GC cycle. It does however use a bit more RAM to store the layout of each object. Right now this GC seems to be slower than the conservative GC, but should be less likely to run out of memory as a result of false positives.
39 строки
1,1 КиБ
Go
39 строки
1,1 КиБ
Go
//go:build (gc.conservative || gc.precise) && !tinygo.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)
|
|
}
|
|
}
|