mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
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>
This commit is contained in:
parent
d4b0bd28ee
commit
5a0f2a7a7c
9 changed files with 32794 additions and 279 deletions
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue