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