runtime: add a test for issue 78081

Contrive to have a bunch of stack shrinking going on during
memclrNoHeapPointersPreemptible calls.

Fails at tip with this patch:

--- a/src/runtime/malloc.go
+++ b/src/runtime/malloc.go
@@ -2184,6 +2184,7 @@ func reusableSize(size uintptr) bool {
 // Use this with care; if the data being cleared is tagged to contain
 // pointers, this allows the GC to run before it is all cleared.
 func memclrNoHeapPointersChunked(size uintptr, x unsafe.Pointer) {
+       y := uintptr(x)
        if getg().preempt {
                // TODO: no need for this, except to test that
                // the preemption point is ok for small zeroings.
@@ -2193,6 +2194,7 @@ func memclrNoHeapPointersChunked(size uintptr, x unsafe.Pointer) {
                // may hold locks, e.g., profiling
                goschedguarded()
        }
+       x = unsafe.Pointer(y)
        // got this from benchmarking. 128k is too small, 512k is too large.
        const chunkBytes = 256 * 1024
        for size > chunkBytes {

Update #78081

Change-Id: Id8f87a4b0d0970cbf971c90ab87703a9e5b3f121
Reviewed-on: https://go-review.googlesource.com/c/go/+/755942
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
Reviewed-by: Keith Randall <khr@google.com>
This commit is contained in:
Keith Randall
2026-03-17 15:43:45 -07:00
parent 9eb830a807
commit 72327dd645

View File

@@ -0,0 +1,47 @@
// run
// Copyright 2026 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import "runtime"
func main() {
runtime.GOMAXPROCS(2)
c := make(chan bool)
for i := 0; i < 16; i++ {
go func() {
var b []byte
for range 100000 {
f(&b)
}
c <- true
}()
}
for i := 0; i < 16; i++ {
<-c
}
}
var n int = 64 // constant, but the compiler doesn't know that
//go:noinline
func f(sink *[]byte) {
useStack(64) // Use 64KB of stack, so that shrinking might happen below.
x := make([]int, n, 128) // on stack
_ = append(x, make([]int, 128-n)...) // memclrNoHeapPointersPreemptible call is here
*sink = make([]byte, 1024) // make some garbage to cause GC
}
//go:noinline
func useStack(depth int) {
var b [128]int
if depth == b[depth%len(b)] { // depth == 0
return
}
useStack(depth - 1)
}