github.com/aloncn/graphics-go@v0.0.1/src/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 const ( 14 typeScalar = 0 15 typePointer = 1 16 ) 17 18 // TestGCInfo tests that various objects in heap, data and bss receive correct GC pointer type info. 19 func TestGCInfo(t *testing.T) { 20 verifyGCInfo(t, "bss Ptr", &bssPtr, infoPtr) 21 verifyGCInfo(t, "bss ScalarPtr", &bssScalarPtr, infoScalarPtr) 22 verifyGCInfo(t, "bss PtrScalar", &bssPtrScalar, infoPtrScalar) 23 verifyGCInfo(t, "bss BigStruct", &bssBigStruct, infoBigStruct()) 24 verifyGCInfo(t, "bss string", &bssString, infoString) 25 verifyGCInfo(t, "bss slice", &bssSlice, infoSlice) 26 verifyGCInfo(t, "bss eface", &bssEface, infoEface) 27 verifyGCInfo(t, "bss iface", &bssIface, infoIface) 28 29 verifyGCInfo(t, "data Ptr", &dataPtr, infoPtr) 30 verifyGCInfo(t, "data ScalarPtr", &dataScalarPtr, infoScalarPtr) 31 verifyGCInfo(t, "data PtrScalar", &dataPtrScalar, infoPtrScalar) 32 verifyGCInfo(t, "data BigStruct", &dataBigStruct, infoBigStruct()) 33 verifyGCInfo(t, "data string", &dataString, infoString) 34 verifyGCInfo(t, "data slice", &dataSlice, infoSlice) 35 verifyGCInfo(t, "data eface", &dataEface, infoEface) 36 verifyGCInfo(t, "data iface", &dataIface, infoIface) 37 38 verifyGCInfo(t, "stack Ptr", new(Ptr), infoPtr) 39 verifyGCInfo(t, "stack ScalarPtr", new(ScalarPtr), infoScalarPtr) 40 verifyGCInfo(t, "stack PtrScalar", new(PtrScalar), infoPtrScalar) 41 verifyGCInfo(t, "stack BigStruct", new(BigStruct), infoBigStruct()) 42 verifyGCInfo(t, "stack string", new(string), infoString) 43 verifyGCInfo(t, "stack slice", new([]string), infoSlice) 44 verifyGCInfo(t, "stack eface", new(interface{}), infoEface) 45 verifyGCInfo(t, "stack iface", new(Iface), infoIface) 46 47 for i := 0; i < 10; i++ { 48 verifyGCInfo(t, "heap Ptr", escape(new(Ptr)), trimDead(padDead(infoPtr))) 49 verifyGCInfo(t, "heap PtrSlice", escape(&make([]*byte, 10)[0]), trimDead(infoPtr10)) 50 verifyGCInfo(t, "heap ScalarPtr", escape(new(ScalarPtr)), trimDead(infoScalarPtr)) 51 verifyGCInfo(t, "heap ScalarPtrSlice", escape(&make([]ScalarPtr, 4)[0]), trimDead(infoScalarPtr4)) 52 verifyGCInfo(t, "heap PtrScalar", escape(new(PtrScalar)), trimDead(infoPtrScalar)) 53 verifyGCInfo(t, "heap BigStruct", escape(new(BigStruct)), trimDead(infoBigStruct())) 54 verifyGCInfo(t, "heap string", escape(new(string)), trimDead(infoString)) 55 verifyGCInfo(t, "heap eface", escape(new(interface{})), trimDead(infoEface)) 56 verifyGCInfo(t, "heap iface", escape(new(Iface)), trimDead(infoIface)) 57 } 58 } 59 60 func verifyGCInfo(t *testing.T, name string, p interface{}, mask0 []byte) { 61 mask := runtime.GCMask(p) 62 if bytes.Compare(mask, mask0) != 0 { 63 t.Errorf("bad GC program for %v:\nwant %+v\ngot %+v", name, mask0, mask) 64 return 65 } 66 } 67 68 func padDead(mask []byte) []byte { 69 // Because the dead bit isn't encoded until the third word, 70 // and because on 32-bit systems a one-word allocation 71 // uses a two-word block, the pointer info for a one-word 72 // object needs to be expanded to include an extra scalar 73 // on 32-bit systems to match the heap bitmap. 74 if runtime.PtrSize == 4 && len(mask) == 1 { 75 return []byte{mask[0], 0} 76 } 77 return mask 78 } 79 80 func trimDead(mask []byte) []byte { 81 for len(mask) > 2 && mask[len(mask)-1] == typeScalar { 82 mask = mask[:len(mask)-1] 83 } 84 return mask 85 } 86 87 var gcinfoSink interface{} 88 89 func escape(p interface{}) interface{} { 90 gcinfoSink = p 91 return p 92 } 93 94 var infoPtr = []byte{typePointer} 95 96 type Ptr struct { 97 *byte 98 } 99 100 var infoPtr10 = []byte{typePointer, typePointer, typePointer, typePointer, typePointer, typePointer, typePointer, typePointer, typePointer, typePointer} 101 102 type ScalarPtr struct { 103 q int 104 w *int 105 e int 106 r *int 107 t int 108 y *int 109 } 110 111 var infoScalarPtr = []byte{typeScalar, typePointer, typeScalar, typePointer, typeScalar, typePointer} 112 113 var infoScalarPtr4 = append(append(append(append([]byte(nil), infoScalarPtr...), infoScalarPtr...), infoScalarPtr...), infoScalarPtr...) 114 115 type PtrScalar struct { 116 q *int 117 w int 118 e *int 119 r int 120 t *int 121 y int 122 } 123 124 var infoPtrScalar = []byte{typePointer, typeScalar, typePointer, typeScalar, typePointer, typeScalar} 125 126 type BigStruct struct { 127 q *int 128 w byte 129 e [17]byte 130 r []byte 131 t int 132 y uint16 133 u uint64 134 i string 135 } 136 137 func infoBigStruct() []byte { 138 switch runtime.GOARCH { 139 case "386", "arm": 140 return []byte{ 141 typePointer, // q *int 142 typeScalar, typeScalar, typeScalar, typeScalar, typeScalar, // w byte; e [17]byte 143 typePointer, typeScalar, typeScalar, // r []byte 144 typeScalar, typeScalar, typeScalar, typeScalar, // t int; y uint16; u uint64 145 typePointer, typeScalar, // i string 146 } 147 case "arm64", "amd64", "mips64", "mips64le", "ppc64", "ppc64le": 148 return []byte{ 149 typePointer, // q *int 150 typeScalar, typeScalar, typeScalar, // w byte; e [17]byte 151 typePointer, typeScalar, typeScalar, // r []byte 152 typeScalar, typeScalar, typeScalar, // t int; y uint16; u uint64 153 typePointer, typeScalar, // i string 154 } 155 case "amd64p32": 156 return []byte{ 157 typePointer, // q *int 158 typeScalar, typeScalar, typeScalar, typeScalar, typeScalar, // w byte; e [17]byte 159 typePointer, typeScalar, typeScalar, // r []byte 160 typeScalar, typeScalar, typeScalar, typeScalar, typeScalar, // t int; y uint16; u uint64 161 typePointer, typeScalar, // i string 162 } 163 default: 164 panic("unknown arch") 165 } 166 } 167 168 type Iface interface { 169 f() 170 } 171 172 type IfaceImpl int 173 174 func (IfaceImpl) f() { 175 } 176 177 var ( 178 // BSS 179 bssPtr Ptr 180 bssScalarPtr ScalarPtr 181 bssPtrScalar PtrScalar 182 bssBigStruct BigStruct 183 bssString string 184 bssSlice []string 185 bssEface interface{} 186 bssIface Iface 187 188 // DATA 189 dataPtr = Ptr{new(byte)} 190 dataScalarPtr = ScalarPtr{q: 1} 191 dataPtrScalar = PtrScalar{w: 1} 192 dataBigStruct = BigStruct{w: 1} 193 dataString = "foo" 194 dataSlice = []string{"foo"} 195 dataEface interface{} = 42 196 dataIface Iface = IfaceImpl(42) 197 198 infoString = []byte{typePointer, typeScalar} 199 infoSlice = []byte{typePointer, typeScalar, typeScalar} 200 infoEface = []byte{typePointer, typePointer} 201 infoIface = []byte{typePointer, typePointer} 202 )