diff options
| author | Josh Bleecher Snyder <josharian@gmail.com> | 2021-09-27 14:27:20 -0700 |
|---|---|---|
| committer | Josh Bleecher Snyder <josharian@gmail.com> | 2021-10-05 19:16:08 +0000 |
| commit | 3100dc1a7fe3f3302cf2419298b0585bc8e83890 (patch) | |
| tree | 5f8955e9fcab05ec6a6e00a20e483950088e1a83 /src/runtime/stack.go | |
| parent | ae83301ab21fd3a0664d1277ee7b313cbf6590d9 (diff) | |
| download | go-3100dc1a7fe3f3302cf2419298b0585bc8e83890.tar.xz | |
cmd/link,runtime: remove relocations from stkobjs
Use an offset from go.func.* instead.
This removes the last relocation from funcdata symbols,
which lets us simplify that code.
size before after Δ %
addr2line 3683218 3680706 -2512 -0.068%
api 4951074 4944850 -6224 -0.126%
asm 4744258 4757586 +13328 +0.281%
buildid 2419986 2418546 -1440 -0.060%
cgo 4218306 4197346 -20960 -0.497%
compile 22132066 22076882 -55184 -0.249%
cover 4432834 4411362 -21472 -0.484%
dist 3111202 3091346 -19856 -0.638%
doc 3583602 3563234 -20368 -0.568%
fix 3023922 3020658 -3264 -0.108%
link 6188034 6164642 -23392 -0.378%
nm 3665826 3646818 -19008 -0.519%
objdump 4015234 4012450 -2784 -0.069%
pack 2155010 2153554 -1456 -0.068%
pprof 13044178 13011522 -32656 -0.250%
test2json 2402146 2383906 -18240 -0.759%
trace 9765410 9736514 -28896 -0.296%
vet 6681250 6655058 -26192 -0.392%
total 104217556 103926980 -290576 -0.279%
relocs before after Δ %
addr2line 25563 25066 -497 -1.944%
api 18409 17176 -1233 -6.698%
asm 18903 18271 -632 -3.343%
buildid 9513 9233 -280 -2.943%
cgo 17103 16222 -881 -5.151%
compile 64825 60421 -4404 -6.794%
cover 19464 18479 -985 -5.061%
dist 10798 10135 -663 -6.140%
doc 13503 12735 -768 -5.688%
fix 11465 10820 -645 -5.626%
link 23214 21849 -1365 -5.880%
nm 25480 24987 -493 -1.935%
objdump 26610 26057 -553 -2.078%
pack 7951 7665 -286 -3.597%
pprof 63964 60761 -3203 -5.008%
test2json 8735 8389 -346 -3.961%
trace 39639 37180 -2459 -6.203%
vet 25970 24044 -1926 -7.416%
total 431108 409489 -21619 -5.015%
Change-Id: I43c26196a008da6d1cb3a782eea2f428778bd569
Reviewed-on: https://go-review.googlesource.com/c/go/+/353138
Trust: Josh Bleecher Snyder <josharian@gmail.com>
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Diffstat (limited to 'src/runtime/stack.go')
| -rw-r--r-- | src/runtime/stack.go | 68 |
1 files changed, 48 insertions, 20 deletions
diff --git a/src/runtime/stack.go b/src/runtime/stack.go index 0946e6975a..efaa799022 100644 --- a/src/runtime/stack.go +++ b/src/runtime/stack.go @@ -691,7 +691,8 @@ func adjustframe(frame *stkframe, arg unsafe.Pointer) bool { // Adjust pointers in all stack objects (whether they are live or not). // See comments in mgcmark.go:scanframeworker. if frame.varp != 0 { - for _, obj := range objs { + for i := range objs { + obj := &objs[i] off := obj.off base := frame.varp // locals base pointer if off >= 0 { @@ -705,7 +706,7 @@ func adjustframe(frame *stkframe, arg unsafe.Pointer) bool { continue } ptrdata := obj.ptrdata() - gcdata := obj.gcdata + gcdata := obj.gcdata() var s *mspan if obj.useGCProg() { // See comments in mgcmark.go:scanstack @@ -1321,7 +1322,7 @@ func getStackMap(frame *stkframe, cache *pcvalueCache, debug bool) (locals, args // We don't actually use argmap in this case, but we need to fake the stack object // record for these frames which contain an internal/abi.RegArgs at a hard-coded offset. // This offset matches the assembly code on amd64 and arm64. - objs = methodValueCallFrameObjs + objs = methodValueCallFrameObjs[:] } else { p := funcdata(f, _FUNCDATA_StackObjects) if p != nil { @@ -1340,23 +1341,33 @@ func getStackMap(frame *stkframe, cache *pcvalueCache, debug bool) (locals, args return } -var ( - abiRegArgsEface interface{} = abi.RegArgs{} - abiRegArgsType *_type = efaceOf(&abiRegArgsEface)._type - methodValueCallFrameObjs = []stackObjectRecord{ - { - off: -int32(alignUp(abiRegArgsType.size, 8)), // It's always the highest address local. - size: int32(abiRegArgsType.size), - _ptrdata: int32(abiRegArgsType.ptrdata), - gcdata: abiRegArgsType.gcdata, - }, - } -) +var methodValueCallFrameObjs [1]stackObjectRecord // initialized in stackobjectinit -func init() { +func stkobjinit() { + var abiRegArgsEface interface{} = abi.RegArgs{} + abiRegArgsType := efaceOf(&abiRegArgsEface)._type if abiRegArgsType.kind&kindGCProg != 0 { throw("abiRegArgsType needs GC Prog, update methodValueCallFrameObjs") } + // Set methodValueCallFrameObjs[0].gcdataoff so that + // stackObjectRecord.gcdata() will work correctly with it. + ptr := uintptr(unsafe.Pointer(&methodValueCallFrameObjs[0])) + var mod *moduledata + for datap := &firstmoduledata; datap != nil; datap = datap.next { + if datap.gofunc <= ptr && ptr < datap.end { + mod = datap + break + } + } + if mod == nil { + throw("methodValueCallFrameObjs is not in a module") + } + methodValueCallFrameObjs[0] = stackObjectRecord{ + off: -int32(alignUp(abiRegArgsType.size, 8)), // It's always the highest address local. + size: int32(abiRegArgsType.size), + _ptrdata: int32(abiRegArgsType.ptrdata), + gcdataoff: uint32(uintptr(unsafe.Pointer(abiRegArgsType.gcdata)) - mod.rodata), + } } // A stackObjectRecord is generated by the compiler for each stack object in a stack frame. @@ -1365,10 +1376,10 @@ type stackObjectRecord struct { // offset in frame // if negative, offset from varp // if non-negative, offset from argp - off int32 - size int32 - _ptrdata int32 // ptrdata, or -ptrdata is GC prog is used - gcdata *byte // pointer map or GC prog of the type + off int32 + size int32 + _ptrdata int32 // ptrdata, or -ptrdata is GC prog is used + gcdataoff uint32 // offset to gcdata from moduledata.rodata } func (r *stackObjectRecord) useGCProg() bool { @@ -1383,6 +1394,23 @@ func (r *stackObjectRecord) ptrdata() uintptr { return uintptr(x) } +// gcdata returns pointer map or GC prog of the type. +func (r *stackObjectRecord) gcdata() *byte { + ptr := uintptr(unsafe.Pointer(r)) + var mod *moduledata + for datap := &firstmoduledata; datap != nil; datap = datap.next { + if datap.gofunc <= ptr && ptr < datap.end { + mod = datap + break + } + } + // If you get a panic here due to a nil mod, + // you may have made a copy of a stackObjectRecord. + // You must use the original pointer. + res := mod.rodata + uintptr(r.gcdataoff) + return (*byte)(unsafe.Pointer(res)) +} + // This is exported as ABI0 via linkname so obj can call it. // //go:nosplit |
