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
14// linked list up the stack, to test lots of stack objects.
15
16type T struct {
17	// points to a heap object. Test will make sure it isn't freed.
18	data *int64
19	// next pointer for a linked list of stack objects
20	next *T
21	// duplicate of next, to stress test the pointer buffers
22	// used during stack tracing.
23	next2 *T
24}
25
26func main() {
27	makelist(nil, 10000)
28}
29
30func makelist(x *T, n int64) {
31	if n%2 != 0 {
32		panic("must be multiple of 2")
33	}
34	if n == 0 {
35		runtime.GC()
36		i := int64(1)
37		for ; x != nil; x, i = x.next, i+1 {
38			// Make sure x.data hasn't been collected.
39			if got := *x.data; got != i {
40				panic(fmt.Sprintf("bad data want %d, got %d", i, got))
41			}
42		}
43		return
44	}
45	// Put 2 objects in each frame, to test intra-frame pointers.
46	// Use both orderings to ensure the linked list isn't always in address order.
47	var a, b T
48	if n%3 == 0 {
49		a.data = newInt(n)
50		a.next = x
51		a.next2 = x
52		b.data = newInt(n - 1)
53		b.next = &a
54		b.next2 = &a
55		x = &b
56	} else {
57		b.data = newInt(n)
58		b.next = x
59		b.next2 = x
60		a.data = newInt(n - 1)
61		a.next = &b
62		a.next2 = &b
63		x = &a
64	}
65
66	makelist(x, n-2)
67}
68
69// big enough and pointer-y enough to not be tinyalloc'd
70type NotTiny struct {
71	n int64
72	p *byte
73}
74
75// newInt allocates n on the heap and returns a pointer to it.
76func newInt(n int64) *int64 {
77	h := &NotTiny{n: n}
78	p := &h.n
79	escape = p
80	return p
81}
82
83var escape *int64
84