diff options
| author | Keith Randall <khr@golang.org> | 2023-11-15 13:38:06 -0800 |
|---|---|---|
| committer | Keith Randall <khr@golang.org> | 2024-11-18 18:43:25 +0000 |
| commit | 5a0f2a7a7c5658f4f3065c265cee61ec1bde9691 (patch) | |
| tree | 7252ff8068e5573b0205d38f83cc0e126d92bf1c /src/runtime/stack.go | |
| parent | d4b0bd28eef0a212930fb196230171a9f11e5ec4 (diff) | |
| download | go-5a0f2a7a7c5658f4f3065c265cee61ec1bde9691.tar.xz | |
cmd/compile: remove gc programs from stack frame objects
This is a two-pronged approach. First, try to keep large objects
off the stack frame. Second, if they do manage to appear anyway,
use straight bitmasks instead of gc programs.
Generally probably a good idea to keep large objects out of stack frames.
But particularly keeping gc programs off the stack simplifies
runtime code a bit.
This CL sets the limit of most stack objects to 131072 bytes (on 64-bit archs).
There can still be large objects if allocated by a late pass, like order, or
they are required to be on the stack, like function arguments.
But the size for the bitmasks for these objects isn't a huge deal,
as we have already have (probably several) bitmasks for the frame
liveness map itself.
Change-Id: I6d2bed0e9aa9ac7499955562c6154f9264061359
Reviewed-on: https://go-review.googlesource.com/c/go/+/542815
Reviewed-by: David Chase <drchase@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Diffstat (limited to 'src/runtime/stack.go')
| -rw-r--r-- | src/runtime/stack.go | 38 |
1 files changed, 9 insertions, 29 deletions
diff --git a/src/runtime/stack.go b/src/runtime/stack.go index aef72d5117..8f11f54cce 100644 --- a/src/runtime/stack.go +++ b/src/runtime/stack.go @@ -722,22 +722,12 @@ func adjustframe(frame *stkframe, adjinfo *adjustinfo) { // we call into morestack.) continue } - ptrdata := obj.ptrdata() - gcdata := obj.gcdata() - var s *mspan - if obj.useGCProg() { - // See comments in mgcmark.go:scanstack - s = materializeGCProg(ptrdata, gcdata) - gcdata = (*byte)(unsafe.Pointer(s.startAddr)) - } - for i := uintptr(0); i < ptrdata; i += goarch.PtrSize { - if *addb(gcdata, i/(8*goarch.PtrSize))>>(i/goarch.PtrSize&7)&1 != 0 { + ptrBytes, gcData := obj.gcdata() + for i := uintptr(0); i < ptrBytes; i += goarch.PtrSize { + if *addb(gcData, i/(8*goarch.PtrSize))>>(i/goarch.PtrSize&7)&1 != 0 { adjustpointer(adjinfo, unsafe.Pointer(p+i)) } } - if s != nil { - dematerializeGCProg(s) - } } } } @@ -1288,24 +1278,14 @@ type stackObjectRecord struct { // if non-negative, offset from argp off int32 size int32 - _ptrdata int32 // ptrdata, or -ptrdata is GC prog is used + ptrBytes int32 gcdataoff uint32 // offset to gcdata from moduledata.rodata } -func (r *stackObjectRecord) useGCProg() bool { - return r._ptrdata < 0 -} - -func (r *stackObjectRecord) ptrdata() uintptr { - x := r._ptrdata - if x < 0 { - return uintptr(-x) - } - return uintptr(x) -} - -// gcdata returns pointer map or GC prog of the type. -func (r *stackObjectRecord) gcdata() *byte { +// gcdata returns the number of bytes that contain pointers, and +// a ptr/nonptr bitmask covering those bytes. +// Note that this bitmask might be larger than internal/abi.MaxPtrmaskBytes. +func (r *stackObjectRecord) gcdata() (uintptr, *byte) { ptr := uintptr(unsafe.Pointer(r)) var mod *moduledata for datap := &firstmoduledata; datap != nil; datap = datap.next { @@ -1318,7 +1298,7 @@ func (r *stackObjectRecord) gcdata() *byte { // 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)) + return uintptr(r.ptrBytes), (*byte)(unsafe.Pointer(res)) } // This is exported as ABI0 via linkname so obj can call it. |
