runtime: refactor markGlobals to findGlobals
Instead of markGlobals calling markRoots unconditionally (which doesn't make sense for -gc=none and -gc=leaking), provide markRoots as a callback function. This is in preparation for -gc=boehm, where the previous design is even more awkward and a callback makes far more sense. I've tested the size impact using `make smoketest XTENSA=0`. There is none, except for two cases: * One with `-opt=0` so const-propagation for the callback didn't take place. * One other on AVR, I don't know why but as it's only 16 bytes in a very specific case I'm going to assume it's just a random change in compiler output that caused a size difference.
Этот коммит содержится в:
родитель
dc449882ad
коммит
4643401a1d
8 изменённых файлов: 20 добавлений и 27 удалений
|
@ -420,7 +420,7 @@ func runGC() (freeBytes uintptr) {
|
|||
|
||||
// Mark phase: mark all reachable objects, recursively.
|
||||
markStack()
|
||||
markGlobals()
|
||||
findGlobals(markRoots)
|
||||
|
||||
if baremetal && hasScheduler {
|
||||
// Channel operations in interrupts may move task pointers around while we are marking.
|
||||
|
|
|
@ -2,13 +2,14 @@
|
|||
|
||||
package runtime
|
||||
|
||||
// This file implements markGlobals for all the files that don't have a more
|
||||
// specific implementation.
|
||||
// This file implements findGlobals for all systems where the start and end of
|
||||
// the globals section can be found through linker-defined symbols.
|
||||
|
||||
// markGlobals marks all globals, which are reachable by definition.
|
||||
// findGlobals finds all globals (which are reachable by definition) and calls
|
||||
// the callback for them.
|
||||
//
|
||||
// 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)
|
||||
func findGlobals(found func(start, end uintptr)) {
|
||||
found(globalsStart, globalsEnd)
|
||||
}
|
||||
|
|
|
@ -100,7 +100,3 @@ func setHeapEnd(newHeapEnd uintptr) {
|
|||
// enough.
|
||||
heapEnd = newHeapEnd
|
||||
}
|
||||
|
||||
func markRoots(start, end uintptr) {
|
||||
// dummy, so that markGlobals will compile
|
||||
}
|
||||
|
|
|
@ -37,7 +37,3 @@ func initHeap() {
|
|||
func setHeapEnd(newHeapEnd uintptr) {
|
||||
// Nothing to do here, this function is never actually called.
|
||||
}
|
||||
|
||||
func markRoots(start, end uintptr) {
|
||||
// dummy, so that markGlobals will compile
|
||||
}
|
||||
|
|
|
@ -54,12 +54,12 @@ type segmentLoadCommand struct {
|
|||
//go:extern _mh_execute_header
|
||||
var libc_mh_execute_header machHeader
|
||||
|
||||
// Mark global variables.
|
||||
// Find global variables in .data/.bss sections.
|
||||
// The MachO linker doesn't seem to provide symbols for the start and end of the
|
||||
// data section. There is get_etext, get_edata, and get_end, but these are
|
||||
// undocumented and don't work with ASLR (which is enabled by default).
|
||||
// Therefore, read the MachO header directly.
|
||||
func markGlobals() {
|
||||
func findGlobals(found func(start, end uintptr)) {
|
||||
// Here is a useful blog post to understand the MachO file format:
|
||||
// https://h3adsh0tzz.com/2020/01/macho-file-format/
|
||||
|
||||
|
@ -103,7 +103,7 @@ func markGlobals() {
|
|||
// This could be improved by only reading the memory areas
|
||||
// covered by sections. That would reduce the amount of memory
|
||||
// scanned a little bit (up to a single VM page).
|
||||
markRoots(offset+cmd.vmaddr, offset+cmd.vmaddr+cmd.vmsize)
|
||||
found(offset+cmd.vmaddr, offset+cmd.vmaddr+cmd.vmsize)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -77,9 +77,9 @@ type elfProgramHeader32 struct {
|
|||
//go:extern __ehdr_start
|
||||
var ehdr_start elfHeader
|
||||
|
||||
// markGlobals marks all globals, which are reachable by definition.
|
||||
// findGlobals finds globals in the .data/.bss sections.
|
||||
// It parses the ELF program header to find writable segments.
|
||||
func markGlobals() {
|
||||
func findGlobals(found func(start, end uintptr)) {
|
||||
// Relevant constants from the ELF specification.
|
||||
// See: https://refspecs.linuxfoundation.org/elf/elf.pdf
|
||||
const (
|
||||
|
@ -99,14 +99,14 @@ func markGlobals() {
|
|||
if header._type == PT_LOAD && header.flags&PF_W != 0 {
|
||||
start := header.vaddr
|
||||
end := start + header.memsz
|
||||
markRoots(start, end)
|
||||
found(start, end)
|
||||
}
|
||||
} else {
|
||||
header := (*elfProgramHeader32)(headerPtr)
|
||||
if header._type == PT_LOAD && header.flags&PF_W != 0 {
|
||||
start := header.vaddr
|
||||
end := start + header.memsz
|
||||
markRoots(start, end)
|
||||
found(start, end)
|
||||
}
|
||||
}
|
||||
headerPtr = unsafe.Add(headerPtr, ehdr_start.phentsize)
|
||||
|
|
|
@ -52,7 +52,7 @@ var module *exeHeader
|
|||
// around 160 bytes of amd64 instructions.
|
||||
// Most of this function is based on the documentation in
|
||||
// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format.
|
||||
func markGlobals() {
|
||||
func findGlobals(found func(start, end uintptr)) {
|
||||
// Constants used in this function.
|
||||
const (
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulehandleexa
|
||||
|
@ -85,7 +85,7 @@ func markGlobals() {
|
|||
// Found a writable section. Scan the entire section for roots.
|
||||
start := uintptr(unsafe.Pointer(module)) + uintptr(section.virtualAddress)
|
||||
end := uintptr(unsafe.Pointer(module)) + uintptr(section.virtualAddress) + uintptr(section.virtualSize)
|
||||
markRoots(start, end)
|
||||
found(start, end)
|
||||
}
|
||||
section = (*peSection)(unsafe.Add(unsafe.Pointer(section), unsafe.Sizeof(peSection{})))
|
||||
}
|
||||
|
|
|
@ -245,17 +245,17 @@ var bssStartSymbol [0]byte
|
|||
//go:extern __bss_end
|
||||
var bssEndSymbol [0]byte
|
||||
|
||||
// Mark global variables.
|
||||
// Find global variables.
|
||||
// The linker script provides __*_start and __*_end symbols that can be used to
|
||||
// scan the given sections. They are already aligned so don't need to be
|
||||
// manually aligned here.
|
||||
func markGlobals() {
|
||||
func findGlobals(found func(start, end uintptr)) {
|
||||
dataStart := uintptr(unsafe.Pointer(&dataStartSymbol))
|
||||
dataEnd := uintptr(unsafe.Pointer(&dataEndSymbol))
|
||||
markRoots(dataStart, dataEnd)
|
||||
found(dataStart, dataEnd)
|
||||
bssStart := uintptr(unsafe.Pointer(&bssStartSymbol))
|
||||
bssEnd := uintptr(unsafe.Pointer(&bssEndSymbol))
|
||||
markRoots(bssStart, bssEnd)
|
||||
found(bssStart, bssEnd)
|
||||
}
|
||||
|
||||
// getContextPtr returns the hblauncher context
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче