Colin Cross | d9c6b80 | 2019-03-19 21:10:31 -0700 | [diff] [blame] | 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 | |
| 7 | package main |
| 8 | |
| 9 | import ( |
| 10 | "fmt" |
| 11 | "runtime" |
| 12 | ) |
| 13 | |
| 14 | // linked list up the stack, to test lots of stack objects. |
| 15 | |
| 16 | type 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 | |
| 26 | func main() { |
| 27 | makelist(nil, 10000) |
| 28 | } |
| 29 | |
| 30 | func 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 |
| 70 | type NotTiny struct { |
| 71 | n int64 |
| 72 | p *byte |
| 73 | } |
| 74 | |
| 75 | // newInt allocates n on the heap and returns a pointer to it. |
| 76 | func newInt(n int64) *int64 { |
| 77 | h := &NotTiny{n: n} |
| 78 | p := &h.n |
| 79 | escape = p |
| 80 | return p |
| 81 | } |
| 82 | |
| 83 | var escape *int64 |