reflect: avoid a bounds check in stack-constrained code

Since CL 682496 we need more stack space to handle bounds checks.
The code modified here normally has no bounds checks, but in -N
builds it still does and thus uses too much stack.

Use unsafe arithmetic to avoid the bounds check.

This will hopefully fix some of the arm64 linux builders.

Change-Id: I5b3096a14b4fb9553e635b7f340e60b8ffba8755
Reviewed-on: https://go-review.googlesource.com/c/go/+/690415
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@google.com>
This commit is contained in:
Keith Randall 2025-07-24 16:41:23 -07:00
parent 3636ced112
commit 91c4f0ccd5

View file

@ -8,6 +8,7 @@ package reflect
import (
"internal/abi"
"internal/goarch"
"unsafe"
)
@ -164,13 +165,18 @@ func moveMakeFuncArgPtrs(ctxt *makeFuncCtxt, args *abi.RegArgs) {
for i, arg := range args.Ints {
// Avoid write barriers! Because our write barrier enqueues what
// was there before, we might enqueue garbage.
// Also avoid bounds checks, we don't have the stack space for it.
// (Normally the prove pass removes them, but for -N builds we
// use too much stack.)
// ptr := &args.Ptrs[i] (but cast from *unsafe.Pointer to *uintptr)
ptr := (*uintptr)(add(unsafe.Pointer(unsafe.SliceData(args.Ptrs[:])), uintptr(i)*goarch.PtrSize, "always in [0:IntArgRegs]"))
if ctxt.regPtrs.Get(i) {
*(*uintptr)(unsafe.Pointer(&args.Ptrs[i])) = arg
*ptr = arg
} else {
// We *must* zero this space ourselves because it's defined in
// assembly code and the GC will scan these pointers. Otherwise,
// there will be garbage here.
*(*uintptr)(unsafe.Pointer(&args.Ptrs[i])) = 0
*ptr = 0
}
}
}