1// run 2 3// Copyright 2023 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 7package main 8 9import ( 10 "runtime" 11 "unsafe" 12) 13 14//go:noinline 15func g(x *byte) *byte { return x } 16 17func main() { 18 slice() 19 str("AAAAAAAA", "BBBBBBBBB") 20} 21 22func wait(done <-chan struct{}) bool { 23 for i := 0; i < 10; i++ { 24 runtime.GC() 25 select { 26 case <-done: 27 return true 28 default: 29 } 30 } 31 return false 32} 33 34func slice() { 35 s := make([]byte, 100) 36 s[0] = 1 37 one := unsafe.SliceData(s) 38 39 done := make(chan struct{}) 40 runtime.SetFinalizer(one, func(*byte) { close(done) }) 41 42 h := g(one) 43 44 if wait(done) { 45 panic("GC'd early") 46 } 47 48 if *h != 1 { 49 panic("lost one") 50 } 51 52 if !wait(done) { 53 panic("never GC'd") 54 } 55} 56 57var strDone = make(chan struct{}) 58 59//go:noinline 60func str(x, y string) { 61 s := x + y // put in temporary on stack 62 p := unsafe.StringData(s) 63 runtime.SetFinalizer(p, func(*byte) { close(strDone) }) 64 65 if wait(strDone) { 66 panic("GC'd early") 67 } 68 69 if *p != 'A' { 70 panic("lost p") 71 } 72 73 if !wait(strDone) { 74 panic("never GC'd") 75 } 76} 77