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.
21 // TestGCInfo tests that various objects in heap, data and bss receive correct GC pointer type info.
22 func TestGCInfo(t
*testing
.T
) {
23 t
.Skip("skipping on gccgo for now")
27 verifyGCInfo(t
, "stack Ptr", &x
, infoPtr
)
32 verifyGCInfo(t
, "stack ScalarPtr", &x
, infoScalarPtr
)
37 verifyGCInfo(t
, "stack PtrScalar", &x
, infoPtrScalar
)
42 verifyGCInfo(t
, "stack BigStruct", &x
, infoBigStruct())
47 verifyGCInfo(t
, "stack string", &x
, infoString
)
52 verifyGCInfo(t
, "stack slice", &x
, infoSlice
)
57 verifyGCInfo(t
, "stack eface", &x
, infoEface
)
62 verifyGCInfo(t
, "stack iface", &x
, infoIface
)
66 for i
:= 0; i
< 10; i
++ {
67 verifyGCInfo(t
, "heap Ptr", escape(new(Ptr
)), trimDead(infoPtr
))
68 verifyGCInfo(t
, "heap PtrSlice", escape(&make([]*byte, 10)[0]), trimDead(infoPtr10
))
69 verifyGCInfo(t
, "heap ScalarPtr", escape(new(ScalarPtr
)), trimDead(infoScalarPtr
))
70 verifyGCInfo(t
, "heap ScalarPtrSlice", escape(&make([]ScalarPtr
, 4)[0]), trimDead(infoScalarPtr4
))
71 verifyGCInfo(t
, "heap PtrScalar", escape(new(PtrScalar
)), trimDead(infoPtrScalar
))
72 verifyGCInfo(t
, "heap BigStruct", escape(new(BigStruct
)), trimDead(infoBigStruct()))
73 verifyGCInfo(t
, "heap string", escape(new(string)), trimDead(infoString
))
74 verifyGCInfo(t
, "heap eface", escape(new(any
)), trimDead(infoEface
))
75 verifyGCInfo(t
, "heap iface", escape(new(Iface
)), trimDead(infoIface
))
79 func verifyGCInfo(t
*testing
.T
, name
string, p any
, mask0
[]byte) {
80 mask
:= runtime
.GCMask(p
)
81 if !bytes
.Equal(mask
, mask0
) {
82 t
.Errorf("bad GC program for %v:\nwant %+v\ngot %+v", name
, mask0
, mask
)
87 func trimDead(mask
[]byte) []byte {
88 for len(mask
) > 0 && mask
[len(mask
)-1] == typeScalar
{
89 mask
= mask
[:len(mask
)-1]
96 func escape(p any
) any
{
101 var infoPtr
= []byte{typePointer
}
107 var infoPtr10
= []byte{typePointer
, typePointer
, typePointer
, typePointer
, typePointer
, typePointer
, typePointer
, typePointer
, typePointer
, typePointer
}
109 type ScalarPtr
struct {
118 var infoScalarPtr
= []byte{typeScalar
, typePointer
, typeScalar
, typePointer
, typeScalar
, typePointer
}
120 var infoScalarPtr4
= append(append(append(append([]byte(nil), infoScalarPtr
...), infoScalarPtr
...), infoScalarPtr
...), infoScalarPtr
...)
122 type PtrScalar
struct {
131 var infoPtrScalar
= []byte{typePointer
, typeScalar
, typePointer
, typeScalar
, typePointer
, typeScalar
}
133 type BigStruct
struct {
144 func infoBigStruct() []byte {
145 switch runtime
.GOARCH
{
146 case "386", "arm", "mips", "mipsle", "riscv":
148 typePointer
, // q *int
149 typeScalar
, typeScalar
, typeScalar
, typeScalar
, typeScalar
, // w byte; e [17]byte
150 typePointer
, typeScalar
, typeScalar
, // r []byte
151 typeScalar
, typeScalar
, typeScalar
, typeScalar
, // t int; y uint16; u uint64
152 typePointer
, typeScalar
, // i string
154 case "arm64", "amd64", "mips64", "mips64le", "ppc64", "ppc64le", "riscv64", "s390x", "wasm":
156 typePointer
, // q *int
157 typeScalar
, typeScalar
, typeScalar
, // w byte; e [17]byte
158 typePointer
, typeScalar
, typeScalar
, // r []byte
159 typeScalar
, typeScalar
, typeScalar
, // t int; y uint16; u uint64
160 typePointer
, typeScalar
, // i string
163 panic("unknown arch")
167 type Iface
interface {
173 func (IfaceImpl
) f() {
179 bssScalarPtr ScalarPtr
180 bssPtrScalar PtrScalar
181 bssBigStruct BigStruct
188 dataPtr
= Ptr
{new(byte)}
189 dataScalarPtr
= ScalarPtr
{q
: 1}
190 dataPtrScalar
= PtrScalar
{w
: 1}
191 dataBigStruct
= BigStruct
{w
: 1}
193 dataSlice
= []string{"foo"}
195 dataIface Iface
= IfaceImpl(42)
197 infoString
= []byte{typePointer
, typeScalar
}
198 infoSlice
= []byte{typePointer
, typeScalar
, typeScalar
}
199 infoEface
= []byte{typeScalar
, typePointer
}
200 infoIface
= []byte{typeScalar
, typePointer
}