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.
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)
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)
40 verifyGCInfo(t, "stack Ptr", &x, infoPtr)
45 verifyGCInfo(t, "stack ScalarPtr", &x, infoScalarPtr)
50 verifyGCInfo(t, "stack PtrScalar", &x, infoPtrScalar)
55 verifyGCInfo(t, "stack BigStruct", &x, infoBigStruct())
60 verifyGCInfo(t, "stack string", &x, infoString)
65 verifyGCInfo(t, "stack slice", &x, infoSlice)
70 verifyGCInfo(t, "stack eface", &x, infoEface)
75 verifyGCInfo(t, "stack iface", &x, infoIface)
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))
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)
100 func trimDead(mask []byte) []byte {
101 for len(mask) > 0 && mask[len(mask)-1] == typeScalar {
102 mask = mask[:len(mask)-1]
107 var infoPtr = []byte{typePointer}
113 var infoPtr10 = []byte{typePointer, typePointer, typePointer, typePointer, typePointer, typePointer, typePointer, typePointer, typePointer, typePointer}
115 type ScalarPtr struct {
124 var infoScalarPtr = []byte{typeScalar, typePointer, typeScalar, typePointer, typeScalar, typePointer}
126 var infoScalarPtr4 = append(append(append(append([]byte(nil), infoScalarPtr...), infoScalarPtr...), infoScalarPtr...), infoScalarPtr...)
128 type PtrScalar struct {
137 var infoPtrScalar = []byte{typePointer, typeScalar, typePointer, typeScalar, typePointer, typeScalar}
139 type BigStruct struct {
150 func infoBigStruct() []byte {
151 switch runtime.GOARCH {
152 case "386", "arm", "mips", "mipsle":
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
160 case "arm64", "amd64", "loong64", "mips64", "mips64le", "ppc64", "ppc64le", "riscv64", "s390x", "wasm":
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
169 panic("unknown arch")
173 type Iface interface {
179 func (IfaceImpl) f() {
185 bssScalarPtr ScalarPtr
186 bssPtrScalar PtrScalar
187 bssBigStruct BigStruct
194 dataPtr = Ptr{new(byte)}
195 dataScalarPtr = ScalarPtr{q: 1}
196 dataPtrScalar = PtrScalar{w: 1}
197 dataBigStruct = BigStruct{w: 1}
199 dataSlice = []string{"foo"}
201 dataIface Iface = IfaceImpl(42)
203 infoString = []byte{typePointer, typeScalar}
204 infoSlice = []byte{typePointer, typeScalar, typeScalar}
205 infoEface = []byte{typeScalar, typePointer}
206 infoIface = []byte{typeScalar, typePointer}