| // run | |
| // Copyright 2018 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| // This test makes sure that ambiguously live arguments work correctly. | |
| package main | |
| import ( | |
| "runtime" | |
| ) | |
| type HeapObj [8]int64 | |
| type StkObj struct { | |
| h *HeapObj | |
| } | |
| var n int | |
| var c int = -1 | |
| func gc() { | |
| // encourage heap object to be collected, and have its finalizer run. | |
| runtime.GC() | |
| runtime.GC() | |
| runtime.GC() | |
| n++ | |
| } | |
| var null StkObj | |
| var sink *HeapObj | |
| //go:noinline | |
| func use(p *StkObj) { | |
| } | |
| //go:noinline | |
| func f(s StkObj, b bool) { | |
| var p *StkObj | |
| if b { | |
| p = &s | |
| } else { | |
| p = &null | |
| } | |
| // use is required here to prevent the conditional | |
| // code above from being executed after the first gc() call. | |
| use(p) | |
| // If b==false, h should be collected here. | |
| gc() // 0 | |
| sink = p.h | |
| gc() // 1 | |
| sink = nil | |
| // If b==true, h should be collected here. | |
| gc() // 2 | |
| } | |
| func fTrue() { | |
| var s StkObj | |
| s.h = new(HeapObj) | |
| c = -1 | |
| n = 0 | |
| runtime.SetFinalizer(s.h, func(h *HeapObj) { | |
| // Remember at what phase the heap object was collected. | |
| c = n | |
| }) | |
| f(s, true) | |
| if c != 2 { | |
| panic("bad liveness") | |
| } | |
| } | |
| func fFalse() { | |
| var s StkObj | |
| s.h = new(HeapObj) | |
| c = -1 | |
| n = 0 | |
| runtime.SetFinalizer(s.h, func(h *HeapObj) { | |
| // Remember at what phase the heap object was collected. | |
| c = n | |
| }) | |
| f(s, false) | |
| if c != 0 { | |
| panic("bad liveness") | |
| } | |
| } | |
| func main() { | |
| fTrue() | |
| fFalse() | |
| } |