github.com/llvm-mirror/llgo@v0.0.0-20190322182713-bf6f0a60fce1/third_party/gofrontend/libgo/go/runtime/gcinfo_test.go (about) 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 // +build ignore 6 7 package runtime_test 8 9 import ( 10 "bytes" 11 "runtime" 12 "testing" 13 ) 14 15 const ( 16 typeScalar = 0 17 typePointer = 1 18 ) 19 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") 23 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) 32 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)) 43 } 44 } 45 46 func verifyGCInfo(t *testing.T, name string, p interface{}, mask0 []byte) { 47 mask := runtime.GCMask(p) 48 if bytes.Compare(mask, mask0) != 0 { 49 t.Errorf("bad GC program for %v:\nwant %+v\ngot %+v", name, mask0, mask) 50 return 51 } 52 } 53 54 func padDead(mask []byte) []byte { 55 // Because the dead bit isn't encoded until the third 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} 62 } 63 return mask 64 } 65 66 func trimDead(mask []byte) []byte { 67 for len(mask) > 2 && mask[len(mask)-1] == typeScalar { 68 mask = mask[:len(mask)-1] 69 } 70 return mask 71 } 72 73 var gcinfoSink interface{} 74 75 func escape(p interface{}) interface{} { 76 gcinfoSink = p 77 return p 78 } 79 80 var infoPtr = []byte{typePointer} 81 82 type Ptr struct { 83 *byte 84 } 85 86 var infoPtr10 = []byte{typePointer, typePointer, typePointer, typePointer, typePointer, typePointer, typePointer, typePointer, typePointer, typePointer} 87 88 type ScalarPtr struct { 89 q int 90 w *int 91 e int 92 r *int 93 t int 94 y *int 95 } 96 97 var infoScalarPtr = []byte{typeScalar, typePointer, typeScalar, typePointer, typeScalar, typePointer} 98 99 var infoScalarPtr4 = append(append(append(append([]byte(nil), infoScalarPtr...), infoScalarPtr...), infoScalarPtr...), infoScalarPtr...) 100 101 type PtrScalar struct { 102 q *int 103 w int 104 e *int 105 r int 106 t *int 107 y int 108 } 109 110 var infoPtrScalar = []byte{typePointer, typeScalar, typePointer, typeScalar, typePointer, typeScalar} 111 112 type BigStruct struct { 113 q *int 114 w byte 115 e [17]byte 116 r []byte 117 t int 118 y uint16 119 u uint64 120 i string 121 } 122 123 func infoBigStruct() []byte { 124 switch runtime.GOARCH { 125 case "386", "arm": 126 return []byte{ 127 typePointer, // q *int 128 typeScalar, typeScalar, typeScalar, typeScalar, typeScalar, // w byte; e [17]byte 129 typePointer, typeScalar, typeScalar, // r []byte 130 typeScalar, typeScalar, typeScalar, typeScalar, // t int; y uint16; u uint64 131 typePointer, typeScalar, // i string 132 } 133 case "arm64", "amd64", "ppc64", "ppc64le": 134 return []byte{ 135 typePointer, // q *int 136 typeScalar, typeScalar, typeScalar, // w byte; e [17]byte 137 typePointer, typeScalar, typeScalar, // r []byte 138 typeScalar, typeScalar, typeScalar, // t int; y uint16; u uint64 139 typePointer, typeScalar, // i string 140 } 141 case "amd64p32": 142 return []byte{ 143 typePointer, // q *int 144 typeScalar, typeScalar, typeScalar, typeScalar, typeScalar, // w byte; e [17]byte 145 typePointer, typeScalar, typeScalar, // r []byte 146 typeScalar, typeScalar, typeScalar, typeScalar, typeScalar, // t int; y uint16; u uint64 147 typePointer, typeScalar, // i string 148 } 149 default: 150 panic("unknown arch") 151 } 152 } 153 154 type Iface interface { 155 f() 156 } 157 158 type IfaceImpl int 159 160 func (IfaceImpl) f() { 161 } 162 163 var ( 164 // BSS 165 bssPtr Ptr 166 bssScalarPtr ScalarPtr 167 bssPtrScalar PtrScalar 168 bssBigStruct BigStruct 169 bssString string 170 bssSlice []string 171 bssEface interface{} 172 bssIface Iface 173 174 // DATA 175 dataPtr = Ptr{new(byte)} 176 dataScalarPtr = ScalarPtr{q: 1} 177 dataPtrScalar = PtrScalar{w: 1} 178 dataBigStruct = BigStruct{w: 1} 179 dataString = "foo" 180 dataSlice = []string{"foo"} 181 dataEface interface{} = 42 182 dataIface Iface = IfaceImpl(42) 183 184 infoString = []byte{typePointer, typeScalar} 185 infoSlice = []byte{typePointer, typeScalar, typeScalar} 186 infoEface = []byte{typePointer, typePointer} 187 infoIface = []byte{typePointer, typePointer} 188 )