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.
20 // TestGCInfo tests that various objects in heap, data and bss receive correct GC pointer type info.
21 func TestGCInfo(t
*testing
.T
) {
22 t
.Skip("skipping on gccgo for now")
24 verifyGCInfo(t
, "stack Ptr", new(Ptr
), infoPtr
)
25 verifyGCInfo(t
, "stack ScalarPtr", new(ScalarPtr
), infoScalarPtr
)
26 verifyGCInfo(t
, "stack PtrScalar", new(PtrScalar
), infoPtrScalar
)
27 verifyGCInfo(t
, "stack BigStruct", new(BigStruct
), infoBigStruct())
28 verifyGCInfo(t
, "stack string", new(string), infoString
)
29 verifyGCInfo(t
, "stack slice", new([]string), infoSlice
)
30 verifyGCInfo(t
, "stack eface", new(interface{}), infoEface
)
31 verifyGCInfo(t
, "stack iface", new(Iface
), infoIface
)
33 for i
:= 0; i
< 10; i
++ {
34 verifyGCInfo(t
, "heap Ptr", escape(new(Ptr
)), trimDead(padDead(infoPtr
)))
35 verifyGCInfo(t
, "heap PtrSlice", escape(&make([]*byte, 10)[0]), trimDead(infoPtr10
))
36 verifyGCInfo(t
, "heap ScalarPtr", escape(new(ScalarPtr
)), trimDead(infoScalarPtr
))
37 verifyGCInfo(t
, "heap ScalarPtrSlice", escape(&make([]ScalarPtr
, 4)[0]), trimDead(infoScalarPtr4
))
38 verifyGCInfo(t
, "heap PtrScalar", escape(new(PtrScalar
)), trimDead(infoPtrScalar
))
39 verifyGCInfo(t
, "heap BigStruct", escape(new(BigStruct
)), trimDead(infoBigStruct()))
40 verifyGCInfo(t
, "heap string", escape(new(string)), trimDead(infoString
))
41 verifyGCInfo(t
, "heap eface", escape(new(interface{})), trimDead(infoEface
))
42 verifyGCInfo(t
, "heap iface", escape(new(Iface
)), trimDead(infoIface
))
46 func verifyGCInfo(t
*testing
.T
, name
string, p
interface{}, mask0
[]byte) {
47 mask
:= runtime
.GCMask(p
)
48 if !bytes
.Equal(mask
, mask0
) {
49 t
.Errorf("bad GC program for %v:\nwant %+v\ngot %+v", name
, mask0
, mask
)
54 func padDead(mask
[]byte) []byte {
55 // Because the dead bit isn't encoded in the second word,
56 // and because on 32-bit systems a one-word allocation
57 // uses a two-word block, the pointer info for a one-word
58 // object needs to be expanded to include an extra scalar
59 // on 32-bit systems to match the heap bitmap.
60 if runtime
.PtrSize
== 4 && len(mask
) == 1 {
61 return []byte{mask
[0], 0}
66 func trimDead(mask
[]byte) []byte {
67 for len(mask
) > 2 && mask
[len(mask
)-1] == typeScalar
{
68 mask
= mask
[:len(mask
)-1]
70 if len(mask
) == 2 && mask
[0] == typeScalar
&& mask
[1] == typeScalar
{
76 var gcinfoSink
interface{}
78 func escape(p
interface{}) interface{} {
83 var infoPtr
= []byte{typePointer
}
89 var infoPtr10
= []byte{typePointer
, typePointer
, typePointer
, typePointer
, typePointer
, typePointer
, typePointer
, typePointer
, typePointer
, typePointer
}
91 type ScalarPtr
struct {
100 var infoScalarPtr
= []byte{typeScalar
, typePointer
, typeScalar
, typePointer
, typeScalar
, typePointer
}
102 var infoScalarPtr4
= append(append(append(append([]byte(nil), infoScalarPtr
...), infoScalarPtr
...), infoScalarPtr
...), infoScalarPtr
...)
104 type PtrScalar
struct {
113 var infoPtrScalar
= []byte{typePointer
, typeScalar
, typePointer
, typeScalar
, typePointer
, typeScalar
}
115 type BigStruct
struct {
126 func infoBigStruct() []byte {
127 switch runtime
.GOARCH
{
128 case "386", "arm", "mips", "mipsle":
130 typePointer
, // q *int
131 typeScalar
, typeScalar
, typeScalar
, typeScalar
, typeScalar
, // w byte; e [17]byte
132 typePointer
, typeScalar
, typeScalar
, // r []byte
133 typeScalar
, typeScalar
, typeScalar
, typeScalar
, // t int; y uint16; u uint64
134 typePointer
, typeScalar
, // i string
136 case "arm64", "amd64", "mips64", "mips64le", "ppc64", "ppc64le", "s390x":
138 typePointer
, // q *int
139 typeScalar
, typeScalar
, typeScalar
, // w byte; e [17]byte
140 typePointer
, typeScalar
, typeScalar
, // r []byte
141 typeScalar
, typeScalar
, typeScalar
, // t int; y uint16; u uint64
142 typePointer
, typeScalar
, // i string
146 typePointer
, // q *int
147 typeScalar
, typeScalar
, typeScalar
, typeScalar
, typeScalar
, // w byte; e [17]byte
148 typePointer
, typeScalar
, typeScalar
, // r []byte
149 typeScalar
, typeScalar
, typeScalar
, typeScalar
, typeScalar
, // t int; y uint16; u uint64
150 typePointer
, typeScalar
, // i string
153 panic("unknown arch")
157 type Iface
interface {
163 func (IfaceImpl
) f() {
169 bssScalarPtr ScalarPtr
170 bssPtrScalar PtrScalar
171 bssBigStruct BigStruct
178 dataPtr
= Ptr
{new(byte)}
179 dataScalarPtr
= ScalarPtr
{q
: 1}
180 dataPtrScalar
= PtrScalar
{w
: 1}
181 dataBigStruct
= BigStruct
{w
: 1}
183 dataSlice
= []string{"foo"}
184 dataEface
interface{} = 42
185 dataIface Iface
= IfaceImpl(42)
187 infoString
= []byte{typePointer
, typeScalar
}
188 infoSlice
= []byte{typePointer
, typeScalar
, typeScalar
}
189 infoEface
= []byte{typePointer
, typePointer
}
190 infoIface
= []byte{typePointer
, typePointer
}