aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/stack.go
diff options
context:
space:
mode:
authorJosh Bleecher Snyder <josharian@gmail.com>2021-09-27 14:27:20 -0700
committerJosh Bleecher Snyder <josharian@gmail.com>2021-10-05 19:16:08 +0000
commit3100dc1a7fe3f3302cf2419298b0585bc8e83890 (patch)
tree5f8955e9fcab05ec6a6e00a20e483950088e1a83 /src/runtime/stack.go
parentae83301ab21fd3a0664d1277ee7b313cbf6590d9 (diff)
downloadgo-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.go68
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