From 5a0f2a7a7c5658f4f3065c265cee61ec1bde9691 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Wed, 15 Nov 2023 13:38:06 -0800 Subject: 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 LUCI-TryBot-Result: Go LUCI Reviewed-by: Cherry Mui --- src/runtime/stack.go | 38 +++++++++----------------------------- 1 file changed, 9 insertions(+), 29 deletions(-) (limited to 'src/runtime/stack.go') 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. -- cgit v1.3