]> Cypherpunks.ru repositories - gostls13.git/blob - src/runtime/gcinfo_test.go
787160dc2779c8583240e35f0fcc60b172842da8
[gostls13.git] / src / runtime / gcinfo_test.go
1 // Copyright 2014 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package runtime_test
6
7 import (
8         "bytes"
9         "runtime"
10         "testing"
11 )
12
13 const (
14         typeScalar  = 0
15         typePointer = 1
16 )
17
18 // TestGCInfo tests that various objects in heap, data and bss receive correct GC pointer type info.
19 func TestGCInfo(t *testing.T) {
20         verifyGCInfo(t, "bss Ptr", &bssPtr, infoPtr)
21         verifyGCInfo(t, "bss ScalarPtr", &bssScalarPtr, infoScalarPtr)
22         verifyGCInfo(t, "bss PtrScalar", &bssPtrScalar, infoPtrScalar)
23         verifyGCInfo(t, "bss BigStruct", &bssBigStruct, infoBigStruct())
24         verifyGCInfo(t, "bss string", &bssString, infoString)
25         verifyGCInfo(t, "bss slice", &bssSlice, infoSlice)
26         verifyGCInfo(t, "bss eface", &bssEface, infoEface)
27         verifyGCInfo(t, "bss iface", &bssIface, infoIface)
28
29         verifyGCInfo(t, "data Ptr", &dataPtr, infoPtr)
30         verifyGCInfo(t, "data ScalarPtr", &dataScalarPtr, infoScalarPtr)
31         verifyGCInfo(t, "data PtrScalar", &dataPtrScalar, infoPtrScalar)
32         verifyGCInfo(t, "data BigStruct", &dataBigStruct, infoBigStruct())
33         verifyGCInfo(t, "data string", &dataString, infoString)
34         verifyGCInfo(t, "data slice", &dataSlice, infoSlice)
35         verifyGCInfo(t, "data eface", &dataEface, infoEface)
36         verifyGCInfo(t, "data iface", &dataIface, infoIface)
37
38         {
39                 var x Ptr
40                 verifyGCInfo(t, "stack Ptr", &x, infoPtr)
41                 runtime.KeepAlive(x)
42         }
43         {
44                 var x ScalarPtr
45                 verifyGCInfo(t, "stack ScalarPtr", &x, infoScalarPtr)
46                 runtime.KeepAlive(x)
47         }
48         {
49                 var x PtrScalar
50                 verifyGCInfo(t, "stack PtrScalar", &x, infoPtrScalar)
51                 runtime.KeepAlive(x)
52         }
53         {
54                 var x BigStruct
55                 verifyGCInfo(t, "stack BigStruct", &x, infoBigStruct())
56                 runtime.KeepAlive(x)
57         }
58         {
59                 var x string
60                 verifyGCInfo(t, "stack string", &x, infoString)
61                 runtime.KeepAlive(x)
62         }
63         {
64                 var x []string
65                 verifyGCInfo(t, "stack slice", &x, infoSlice)
66                 runtime.KeepAlive(x)
67         }
68         {
69                 var x any
70                 verifyGCInfo(t, "stack eface", &x, infoEface)
71                 runtime.KeepAlive(x)
72         }
73         {
74                 var x Iface
75                 verifyGCInfo(t, "stack iface", &x, infoIface)
76                 runtime.KeepAlive(x)
77         }
78
79         for i := 0; i < 10; i++ {
80                 verifyGCInfo(t, "heap Ptr", runtime.Escape(new(Ptr)), trimDead(infoPtr))
81                 verifyGCInfo(t, "heap PtrSlice", runtime.Escape(&make([]*byte, 10)[0]), trimDead(infoPtr10))
82                 verifyGCInfo(t, "heap ScalarPtr", runtime.Escape(new(ScalarPtr)), trimDead(infoScalarPtr))
83                 verifyGCInfo(t, "heap ScalarPtrSlice", runtime.Escape(&make([]ScalarPtr, 4)[0]), trimDead(infoScalarPtr4))
84                 verifyGCInfo(t, "heap PtrScalar", runtime.Escape(new(PtrScalar)), trimDead(infoPtrScalar))
85                 verifyGCInfo(t, "heap BigStruct", runtime.Escape(new(BigStruct)), trimDead(infoBigStruct()))
86                 verifyGCInfo(t, "heap string", runtime.Escape(new(string)), trimDead(infoString))
87                 verifyGCInfo(t, "heap eface", runtime.Escape(new(any)), trimDead(infoEface))
88                 verifyGCInfo(t, "heap iface", runtime.Escape(new(Iface)), trimDead(infoIface))
89         }
90 }
91
92 func verifyGCInfo(t *testing.T, name string, p any, mask0 []byte) {
93         mask := runtime.GCMask(p)
94         if !bytes.Equal(mask, mask0) {
95                 t.Errorf("bad GC program for %v:\nwant %+v\ngot  %+v", name, mask0, mask)
96                 return
97         }
98 }
99
100 func trimDead(mask []byte) []byte {
101         for len(mask) > 0 && mask[len(mask)-1] == typeScalar {
102                 mask = mask[:len(mask)-1]
103         }
104         return mask
105 }
106
107 var infoPtr = []byte{typePointer}
108
109 type Ptr struct {
110         *byte
111 }
112
113 var infoPtr10 = []byte{typePointer, typePointer, typePointer, typePointer, typePointer, typePointer, typePointer, typePointer, typePointer, typePointer}
114
115 type ScalarPtr struct {
116         q int
117         w *int
118         e int
119         r *int
120         t int
121         y *int
122 }
123
124 var infoScalarPtr = []byte{typeScalar, typePointer, typeScalar, typePointer, typeScalar, typePointer}
125
126 var infoScalarPtr4 = append(append(append(append([]byte(nil), infoScalarPtr...), infoScalarPtr...), infoScalarPtr...), infoScalarPtr...)
127
128 type PtrScalar struct {
129         q *int
130         w int
131         e *int
132         r int
133         t *int
134         y int
135 }
136
137 var infoPtrScalar = []byte{typePointer, typeScalar, typePointer, typeScalar, typePointer, typeScalar}
138
139 type BigStruct struct {
140         q *int
141         w byte
142         e [17]byte
143         r []byte
144         t int
145         y uint16
146         u uint64
147         i string
148 }
149
150 func infoBigStruct() []byte {
151         switch runtime.GOARCH {
152         case "386", "arm", "mips", "mipsle":
153                 return []byte{
154                         typePointer,                                                // q *int
155                         typeScalar, typeScalar, typeScalar, typeScalar, typeScalar, // w byte; e [17]byte
156                         typePointer, typeScalar, typeScalar, // r []byte
157                         typeScalar, typeScalar, typeScalar, typeScalar, // t int; y uint16; u uint64
158                         typePointer, typeScalar, // i string
159                 }
160         case "arm64", "amd64", "loong64", "mips64", "mips64le", "ppc64", "ppc64le", "riscv64", "s390x", "wasm":
161                 return []byte{
162                         typePointer,                        // q *int
163                         typeScalar, typeScalar, typeScalar, // w byte; e [17]byte
164                         typePointer, typeScalar, typeScalar, // r []byte
165                         typeScalar, typeScalar, typeScalar, // t int; y uint16; u uint64
166                         typePointer, typeScalar, // i string
167                 }
168         default:
169                 panic("unknown arch")
170         }
171 }
172
173 type Iface interface {
174         f()
175 }
176
177 type IfaceImpl int
178
179 func (IfaceImpl) f() {
180 }
181
182 var (
183         // BSS
184         bssPtr       Ptr
185         bssScalarPtr ScalarPtr
186         bssPtrScalar PtrScalar
187         bssBigStruct BigStruct
188         bssString    string
189         bssSlice     []string
190         bssEface     any
191         bssIface     Iface
192
193         // DATA
194         dataPtr             = Ptr{new(byte)}
195         dataScalarPtr       = ScalarPtr{q: 1}
196         dataPtrScalar       = PtrScalar{w: 1}
197         dataBigStruct       = BigStruct{w: 1}
198         dataString          = "foo"
199         dataSlice           = []string{"foo"}
200         dataEface     any   = 42
201         dataIface     Iface = IfaceImpl(42)
202
203         infoString = []byte{typePointer, typeScalar}
204         infoSlice  = []byte{typePointer, typeScalar, typeScalar}
205         infoEface  = []byte{typeScalar, typePointer}
206         infoIface  = []byte{typeScalar, typePointer}
207 )