github.com/prattmic/llgo-embedded@v0.0.0-20150820070356-41cfecea0e1e/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 package runtime_test 6 7 import ( 8 "bytes" 9 "runtime" 10 "testing" 11 ) 12 13 // TestGCInfo tests that various objects in heap, data and bss receive correct GC pointer type info. 14 func TestGCInfo(t *testing.T) { 15 t.Skip("skipping on gccgo for now") 16 verifyGCInfo(t, "bss ScalarPtr", &bssScalarPtr, nonStackInfo(infoScalarPtr)) 17 verifyGCInfo(t, "bss PtrScalar", &bssPtrScalar, nonStackInfo(infoPtrScalar)) 18 verifyGCInfo(t, "bss BigStruct", &bssBigStruct, nonStackInfo(infoBigStruct())) 19 verifyGCInfo(t, "bss string", &bssString, nonStackInfo(infoString)) 20 verifyGCInfo(t, "bss slice", &bssSlice, nonStackInfo(infoSlice)) 21 verifyGCInfo(t, "bss eface", &bssEface, nonStackInfo(infoEface)) 22 verifyGCInfo(t, "bss iface", &bssIface, nonStackInfo(infoIface)) 23 24 verifyGCInfo(t, "data ScalarPtr", &dataScalarPtr, nonStackInfo(infoScalarPtr)) 25 verifyGCInfo(t, "data PtrScalar", &dataPtrScalar, nonStackInfo(infoPtrScalar)) 26 verifyGCInfo(t, "data BigStruct", &dataBigStruct, nonStackInfo(infoBigStruct())) 27 verifyGCInfo(t, "data string", &dataString, nonStackInfo(infoString)) 28 verifyGCInfo(t, "data slice", &dataSlice, nonStackInfo(infoSlice)) 29 verifyGCInfo(t, "data eface", &dataEface, nonStackInfo(infoEface)) 30 verifyGCInfo(t, "data iface", &dataIface, nonStackInfo(infoIface)) 31 32 verifyGCInfo(t, "stack ScalarPtr", new(ScalarPtr), infoScalarPtr) 33 verifyGCInfo(t, "stack PtrScalar", new(PtrScalar), infoPtrScalar) 34 verifyGCInfo(t, "stack BigStruct", new(BigStruct), infoBigStruct()) 35 verifyGCInfo(t, "stack string", new(string), infoString) 36 verifyGCInfo(t, "stack slice", new([]string), infoSlice) 37 verifyGCInfo(t, "stack eface", new(interface{}), infoEface) 38 verifyGCInfo(t, "stack iface", new(Iface), infoIface) 39 40 for i := 0; i < 10; i++ { 41 verifyGCInfo(t, "heap ScalarPtr", escape(new(ScalarPtr)), nonStackInfo(infoScalarPtr)) 42 verifyGCInfo(t, "heap PtrScalar", escape(new(PtrScalar)), nonStackInfo(infoPtrScalar)) 43 verifyGCInfo(t, "heap BigStruct", escape(new(BigStruct)), nonStackInfo(infoBigStruct())) 44 verifyGCInfo(t, "heap string", escape(new(string)), nonStackInfo(infoString)) 45 verifyGCInfo(t, "heap eface", escape(new(interface{})), nonStackInfo(infoEface)) 46 verifyGCInfo(t, "heap iface", escape(new(Iface)), nonStackInfo(infoIface)) 47 } 48 49 } 50 51 func verifyGCInfo(t *testing.T, name string, p interface{}, mask0 []byte) { 52 mask := /* runtime.GCMask(p) */ []byte(nil) 53 if len(mask) > len(mask0) { 54 mask0 = append(mask0, BitsDead) 55 mask = mask[:len(mask0)] 56 } 57 if bytes.Compare(mask, mask0) != 0 { 58 t.Errorf("bad GC program for %v:\nwant %+v\ngot %+v", name, mask0, mask) 59 return 60 } 61 } 62 63 func nonStackInfo(mask []byte) []byte { 64 // BitsDead is replaced with BitsScalar everywhere except stacks. 65 mask1 := make([]byte, len(mask)) 66 mw := false 67 for i, v := range mask { 68 if !mw && v == BitsDead { 69 v = BitsScalar 70 } 71 mw = !mw && v == BitsMultiWord 72 mask1[i] = v 73 } 74 return mask1 75 } 76 77 var gcinfoSink interface{} 78 79 func escape(p interface{}) interface{} { 80 gcinfoSink = p 81 return p 82 } 83 84 const ( 85 BitsDead = iota 86 BitsScalar 87 BitsPointer 88 BitsMultiWord 89 ) 90 91 const ( 92 BitsString = iota // unused 93 BitsSlice // unused 94 BitsIface 95 BitsEface 96 ) 97 98 type ScalarPtr struct { 99 q int 100 w *int 101 e int 102 r *int 103 t int 104 y *int 105 } 106 107 var infoScalarPtr = []byte{BitsScalar, BitsPointer, BitsScalar, BitsPointer, BitsScalar, BitsPointer} 108 109 type PtrScalar struct { 110 q *int 111 w int 112 e *int 113 r int 114 t *int 115 y int 116 } 117 118 var infoPtrScalar = []byte{BitsPointer, BitsScalar, BitsPointer, BitsScalar, BitsPointer, BitsScalar} 119 120 type BigStruct struct { 121 q *int 122 w byte 123 e [17]byte 124 r []byte 125 t int 126 y uint16 127 u uint64 128 i string 129 } 130 131 func infoBigStruct() []byte { 132 switch runtime.GOARCH { 133 case "386", "arm": 134 return []byte{ 135 BitsPointer, // q *int 136 BitsScalar, BitsScalar, BitsScalar, BitsScalar, BitsScalar, // w byte; e [17]byte 137 BitsPointer, BitsDead, BitsDead, // r []byte 138 BitsScalar, BitsScalar, BitsScalar, BitsScalar, // t int; y uint16; u uint64 139 BitsPointer, BitsDead, // i string 140 } 141 case "amd64": 142 return []byte{ 143 BitsPointer, // q *int 144 BitsScalar, BitsScalar, BitsScalar, // w byte; e [17]byte 145 BitsPointer, BitsDead, BitsDead, // r []byte 146 BitsScalar, BitsScalar, BitsScalar, // t int; y uint16; u uint64 147 BitsPointer, BitsDead, // i string 148 } 149 case "amd64p32": 150 return []byte{ 151 BitsPointer, // q *int 152 BitsScalar, BitsScalar, BitsScalar, BitsScalar, BitsScalar, // w byte; e [17]byte 153 BitsPointer, BitsDead, BitsDead, // r []byte 154 BitsScalar, BitsScalar, BitsDead, BitsScalar, BitsScalar, // t int; y uint16; u uint64 155 BitsPointer, BitsDead, // i string 156 } 157 default: 158 panic("unknown arch") 159 } 160 } 161 162 type Iface interface { 163 f() 164 } 165 166 type IfaceImpl int 167 168 func (IfaceImpl) f() { 169 } 170 171 var ( 172 // BSS 173 bssScalarPtr ScalarPtr 174 bssPtrScalar PtrScalar 175 bssBigStruct BigStruct 176 bssString string 177 bssSlice []string 178 bssEface interface{} 179 bssIface Iface 180 181 // DATA 182 dataScalarPtr = ScalarPtr{q: 1} 183 dataPtrScalar = PtrScalar{w: 1} 184 dataBigStruct = BigStruct{w: 1} 185 dataString = "foo" 186 dataSlice = []string{"foo"} 187 dataEface interface{} = 42 188 dataIface Iface = IfaceImpl(42) 189 190 infoString = []byte{BitsPointer, BitsDead} 191 infoSlice = []byte{BitsPointer, BitsDead, BitsDead} 192 infoEface = []byte{BitsMultiWord, BitsEface} 193 infoIface = []byte{BitsMultiWord, BitsIface} 194 )