blob: 8bb8fb3270581438908873f5e35e6b84ae0f4d5d [file] [log] [blame]
// 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()
}