1// run 2 3// Copyright 2018 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// This test makes sure that ambiguously live arguments work correctly. 8 9package main 10 11import ( 12 "runtime" 13) 14 15type HeapObj [8]int64 16 17type StkObj struct { 18 h *HeapObj 19} 20 21var n int 22var c int = -1 23 24func gc() { 25 // encourage heap object to be collected, and have its finalizer run. 26 runtime.GC() 27 runtime.GC() 28 runtime.GC() 29 n++ 30} 31 32var null StkObj 33 34var sink *HeapObj 35 36//go:noinline 37func use(p *StkObj) { 38} 39 40//go:noinline 41func f(s StkObj, b bool) { 42 var p *StkObj 43 if b { 44 p = &s 45 } else { 46 p = &null 47 } 48 // use is required here to prevent the conditional 49 // code above from being executed after the first gc() call. 50 use(p) 51 // If b==false, h should be collected here. 52 gc() // 0 53 sink = p.h 54 gc() // 1 55 sink = nil 56 // If b==true, h should be collected here. 57 gc() // 2 58} 59 60func fTrue() { 61 var s StkObj 62 s.h = new(HeapObj) 63 c = -1 64 n = 0 65 runtime.SetFinalizer(s.h, func(h *HeapObj) { 66 // Remember at what phase the heap object was collected. 67 c = n 68 }) 69 f(s, true) 70 if c != 2 { 71 panic("bad liveness") 72 } 73} 74 75func fFalse() { 76 var s StkObj 77 s.h = new(HeapObj) 78 c = -1 79 n = 0 80 runtime.SetFinalizer(s.h, func(h *HeapObj) { 81 // Remember at what phase the heap object was collected. 82 c = n 83 }) 84 f(s, false) 85 if c != 0 { 86 panic("bad liveness") 87 } 88} 89 90func main() { 91 fTrue() 92 fFalse() 93} 94