1// run
2
3// Copyright 2019 The Go Authors. All rights reserved.
4// Use of this source code is governed by a BSD-style
5// license that can be found in the LICENSE file.
6
7// Issue 30041: copying results of a reflect-generated
8// call on stack should not have write barrier.
9
10package main
11
12import (
13	"reflect"
14	"runtime"
15	"unsafe"
16)
17
18var badPtr uintptr
19
20var sink []byte
21
22func init() {
23	// Allocate large enough to use largeAlloc.
24	b := make([]byte, 1<<16-1)
25	sink = b // force heap allocation
26	//  Any space between the object and the end of page is invalid to point to.
27	badPtr = uintptr(unsafe.Pointer(&b[len(b)-1])) + 1
28}
29
30type ft func() *int
31
32var fn ft
33
34func rf([]reflect.Value) []reflect.Value {
35	a := reflect.ValueOf((*int)(nil))
36	return []reflect.Value{a}
37}
38
39const N = 1000
40
41func main() {
42	fn = reflect.MakeFunc(reflect.TypeOf(fn), rf).Interface().(ft)
43
44	// Keep running GC so the write barrier is on.
45	go func() {
46		for i := 0; i < N; i++ {
47			runtime.GC()
48		}
49	}()
50
51	var x [10]uintptr
52	for i := range x {
53		x[i] = badPtr
54	}
55	for i := 0; i < N; i++ {
56		runtime.Gosched()
57		use(x) // prepare bad pointers on stack
58		fn()
59	}
60}
61
62//go:noinline
63func use([10]uintptr) {}
64