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.
|
// Mark phase: mark all reachable objects, recursively.
|
||||||
markStack()
|
markStack()
|
||||||
markGlobals()
|
findGlobals(markRoots)
|
||||||
|
|
||||||
if baremetal && hasScheduler {
|
if baremetal && hasScheduler {
|
||||||
// Channel operations in interrupts may move task pointers around while we are marking.
|
// Channel operations in interrupts may move task pointers around while we are marking.
|
||||||
|
|
|
@ -2,13 +2,14 @@
|
||||||
|
|
||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
// This file implements markGlobals for all the files that don't have a more
|
// This file implements findGlobals for all systems where the start and end of
|
||||||
// specific implementation.
|
// 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
|
// This implementation marks all globals conservatively and assumes it can use
|
||||||
// linker-defined symbols for the start and end of the .data section.
|
// linker-defined symbols for the start and end of the .data section.
|
||||||
func markGlobals() {
|
func findGlobals(found func(start, end uintptr)) {
|
||||||
markRoots(globalsStart, globalsEnd)
|
found(globalsStart, globalsEnd)
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,7 +100,3 @@ func setHeapEnd(newHeapEnd uintptr) {
|
||||||
// enough.
|
// enough.
|
||||||
heapEnd = newHeapEnd
|
heapEnd = newHeapEnd
|
||||||
}
|
}
|
||||||
|
|
||||||
func markRoots(start, end uintptr) {
|
|
||||||
// dummy, so that markGlobals will compile
|
|
||||||
}
|
|
||||||
|
|
|
@ -37,7 +37,3 @@ func initHeap() {
|
||||||
func setHeapEnd(newHeapEnd uintptr) {
|
func setHeapEnd(newHeapEnd uintptr) {
|
||||||
// Nothing to do here, this function is never actually called.
|
// 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
|
//go:extern _mh_execute_header
|
||||||
var libc_mh_execute_header machHeader
|
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
|
// 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
|
// 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).
|
// undocumented and don't work with ASLR (which is enabled by default).
|
||||||
// Therefore, read the MachO header directly.
|
// 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:
|
// Here is a useful blog post to understand the MachO file format:
|
||||||
// https://h3adsh0tzz.com/2020/01/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
|
// This could be improved by only reading the memory areas
|
||||||
// covered by sections. That would reduce the amount of memory
|
// covered by sections. That would reduce the amount of memory
|
||||||
// scanned a little bit (up to a single VM page).
|
// 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
|
//go:extern __ehdr_start
|
||||||
var ehdr_start elfHeader
|
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.
|
// 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.
|
// Relevant constants from the ELF specification.
|
||||||
// See: https://refspecs.linuxfoundation.org/elf/elf.pdf
|
// See: https://refspecs.linuxfoundation.org/elf/elf.pdf
|
||||||
const (
|
const (
|
||||||
|
@ -99,14 +99,14 @@ func markGlobals() {
|
||||||
if header._type == PT_LOAD && header.flags&PF_W != 0 {
|
if header._type == PT_LOAD && header.flags&PF_W != 0 {
|
||||||
start := header.vaddr
|
start := header.vaddr
|
||||||
end := start + header.memsz
|
end := start + header.memsz
|
||||||
markRoots(start, end)
|
found(start, end)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
header := (*elfProgramHeader32)(headerPtr)
|
header := (*elfProgramHeader32)(headerPtr)
|
||||||
if header._type == PT_LOAD && header.flags&PF_W != 0 {
|
if header._type == PT_LOAD && header.flags&PF_W != 0 {
|
||||||
start := header.vaddr
|
start := header.vaddr
|
||||||
end := start + header.memsz
|
end := start + header.memsz
|
||||||
markRoots(start, end)
|
found(start, end)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
headerPtr = unsafe.Add(headerPtr, ehdr_start.phentsize)
|
headerPtr = unsafe.Add(headerPtr, ehdr_start.phentsize)
|
||||||
|
|
|
@ -52,7 +52,7 @@ var module *exeHeader
|
||||||
// around 160 bytes of amd64 instructions.
|
// around 160 bytes of amd64 instructions.
|
||||||
// Most of this function is based on the documentation in
|
// Most of this function is based on the documentation in
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format.
|
// 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.
|
// Constants used in this function.
|
||||||
const (
|
const (
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulehandleexa
|
// 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.
|
// Found a writable section. Scan the entire section for roots.
|
||||||
start := uintptr(unsafe.Pointer(module)) + uintptr(section.virtualAddress)
|
start := uintptr(unsafe.Pointer(module)) + uintptr(section.virtualAddress)
|
||||||
end := uintptr(unsafe.Pointer(module)) + uintptr(section.virtualAddress) + uintptr(section.virtualSize)
|
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{})))
|
section = (*peSection)(unsafe.Add(unsafe.Pointer(section), unsafe.Sizeof(peSection{})))
|
||||||
}
|
}
|
||||||
|
|
|
@ -245,17 +245,17 @@ var bssStartSymbol [0]byte
|
||||||
//go:extern __bss_end
|
//go:extern __bss_end
|
||||||
var bssEndSymbol [0]byte
|
var bssEndSymbol [0]byte
|
||||||
|
|
||||||
// Mark global variables.
|
// Find global variables.
|
||||||
// The linker script provides __*_start and __*_end symbols that can be used to
|
// 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
|
// scan the given sections. They are already aligned so don't need to be
|
||||||
// manually aligned here.
|
// manually aligned here.
|
||||||
func markGlobals() {
|
func findGlobals(found func(start, end uintptr)) {
|
||||||
dataStart := uintptr(unsafe.Pointer(&dataStartSymbol))
|
dataStart := uintptr(unsafe.Pointer(&dataStartSymbol))
|
||||||
dataEnd := uintptr(unsafe.Pointer(&dataEndSymbol))
|
dataEnd := uintptr(unsafe.Pointer(&dataEndSymbol))
|
||||||
markRoots(dataStart, dataEnd)
|
found(dataStart, dataEnd)
|
||||||
bssStart := uintptr(unsafe.Pointer(&bssStartSymbol))
|
bssStart := uintptr(unsafe.Pointer(&bssStartSymbol))
|
||||||
bssEnd := uintptr(unsafe.Pointer(&bssEndSymbol))
|
bssEnd := uintptr(unsafe.Pointer(&bssEndSymbol))
|
||||||
markRoots(bssStart, bssEnd)
|
found(bssStart, bssEnd)
|
||||||
}
|
}
|
||||||
|
|
||||||
// getContextPtr returns the hblauncher context
|
// getContextPtr returns the hblauncher context
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче