blob: 7d8a1698cbc2882e2e7b3a06cd7007d642752b08 [file] [log] [blame]
Cherry Zhang7e987b72019-01-31 20:29:21 -05001// 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) {}