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>
This commit is contained in:
Josh Bleecher Snyder 2021-09-27 14:27:20 -07:00
parent ae83301ab2
commit 3100dc1a7f
8 changed files with 69 additions and 60 deletions

View file

@ -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