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
7package main
8
9import (
10	"fmt"
11	"runtime"
12)
13
14type HeapObj [8]int64
15
16type StkObj struct {
17	h *HeapObj
18}
19
20var n int
21var c int = -1
22
23func gc() {
24	// encourage heap object to be collected, and have its finalizer run.
25	runtime.GC()
26	runtime.GC()
27	runtime.GC()
28	n++
29}
30
31func main() {
32	f()
33	gc() // prior to stack objects, heap object is not collected until here
34	if c < 0 {
35		panic("heap object never collected")
36	}
37	if c != 1 {
38		panic(fmt.Sprintf("expected collection at phase 1, got phase %d", c))
39	}
40}
41
42func f() {
43	var s StkObj
44	s.h = new(HeapObj)
45	runtime.SetFinalizer(s.h, func(h *HeapObj) {
46		// Remember at what phase the heap object was collected.
47		c = n
48	})
49	g(&s)
50	gc()
51}
52
53func g(s *StkObj) {
54	gc() // heap object is still live here
55	runtime.KeepAlive(s)
56	gc() // heap object should be collected here
57}
58