|  | // 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. | 
|  |  | 
|  | package main | 
|  |  | 
|  | import ( | 
|  | "fmt" | 
|  | "runtime" | 
|  | ) | 
|  |  | 
|  | // linked list up the stack, to test lots of stack objects. | 
|  |  | 
|  | type T struct { | 
|  | // points to a heap object. Test will make sure it isn't freed. | 
|  | data *int64 | 
|  | // next pointer for a linked list of stack objects | 
|  | next *T | 
|  | // duplicate of next, to stress test the pointer buffers | 
|  | // used during stack tracing. | 
|  | next2 *T | 
|  | } | 
|  |  | 
|  | func main() { | 
|  | makelist(nil, 10000) | 
|  | } | 
|  |  | 
|  | func makelist(x *T, n int64) { | 
|  | if n%2 != 0 { | 
|  | panic("must be multiple of 2") | 
|  | } | 
|  | if n == 0 { | 
|  | runtime.GC() | 
|  | i := int64(1) | 
|  | for ; x != nil; x, i = x.next, i+1 { | 
|  | // Make sure x.data hasn't been collected. | 
|  | if got := *x.data; got != i { | 
|  | panic(fmt.Sprintf("bad data want %d, got %d", i, got)) | 
|  | } | 
|  | } | 
|  | return | 
|  | } | 
|  | // Put 2 objects in each frame, to test intra-frame pointers. | 
|  | // Use both orderings to ensure the linked list isn't always in address order. | 
|  | var a, b T | 
|  | if n%3 == 0 { | 
|  | a.data = newInt(n) | 
|  | a.next = x | 
|  | a.next2 = x | 
|  | b.data = newInt(n - 1) | 
|  | b.next = &a | 
|  | b.next2 = &a | 
|  | x = &b | 
|  | } else { | 
|  | b.data = newInt(n) | 
|  | b.next = x | 
|  | b.next2 = x | 
|  | a.data = newInt(n - 1) | 
|  | a.next = &b | 
|  | a.next2 = &b | 
|  | x = &a | 
|  | } | 
|  |  | 
|  | makelist(x, n-2) | 
|  | } | 
|  |  | 
|  | // big enough and pointer-y enough to not be tinyalloc'd | 
|  | type NotTiny struct { | 
|  | n int64 | 
|  | p *byte | 
|  | } | 
|  |  | 
|  | // newInt allocates n on the heap and returns a pointer to it. | 
|  | func newInt(n int64) *int64 { | 
|  | h := &NotTiny{n: n} | 
|  | p := &h.n | 
|  | escape = p | 
|  | return p | 
|  | } | 
|  |  | 
|  | var escape *int64 |