PR go/83787
[official-gcc.git] / libgo / go / runtime / gcinfo_test.go
blob4ac67dc4be2f13413e54075254d90efa81750f36
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.
5 // +build ignore
7 package runtime_test
9 import (
10 "bytes"
11 "runtime"
12 "testing"
15 const (
16 typeScalar = 0
17 typePointer = 1
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)
50 return
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}
63 return mask
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 {
71 mask = mask[:0]
73 return mask
76 var gcinfoSink interface{}
78 func escape(p interface{}) interface{} {
79 gcinfoSink = p
80 return p
83 var infoPtr = []byte{typePointer}
85 type Ptr struct {
86 *byte
89 var infoPtr10 = []byte{typePointer, typePointer, typePointer, typePointer, typePointer, typePointer, typePointer, typePointer, typePointer, typePointer}
91 type ScalarPtr struct {
92 q int
93 w *int
94 e int
95 r *int
96 t int
97 y *int
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 {
105 q *int
106 w int
107 e *int
108 r int
109 t *int
110 y int
113 var infoPtrScalar = []byte{typePointer, typeScalar, typePointer, typeScalar, typePointer, typeScalar}
115 type BigStruct struct {
116 q *int
117 w byte
118 e [17]byte
119 r []byte
120 t int
121 y uint16
122 u uint64
123 i string
126 func infoBigStruct() []byte {
127 switch runtime.GOARCH {
128 case "386", "arm", "mips", "mipsle":
129 return []byte{
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":
137 return []byte{
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
144 case "amd64p32":
145 return []byte{
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
152 default:
153 panic("unknown arch")
157 type Iface interface {
161 type IfaceImpl int
163 func (IfaceImpl) f() {
166 var (
167 // BSS
168 bssPtr Ptr
169 bssScalarPtr ScalarPtr
170 bssPtrScalar PtrScalar
171 bssBigStruct BigStruct
172 bssString string
173 bssSlice []string
174 bssEface interface{}
175 bssIface Iface
177 // DATA
178 dataPtr = Ptr{new(byte)}
179 dataScalarPtr = ScalarPtr{q: 1}
180 dataPtrScalar = PtrScalar{w: 1}
181 dataBigStruct = BigStruct{w: 1}
182 dataString = "foo"
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}