github.com/megatontech/mynoteforgo@v0.0.0-20200507084910-5d0c6ea6e890/源码/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 { 39 var x Ptr 40 verifyGCInfo(t, "stack Ptr", &x, infoPtr) 41 runtime.KeepAlive(x) 42 } 43 { 44 var x ScalarPtr 45 verifyGCInfo(t, "stack ScalarPtr", &x, infoScalarPtr) 46 runtime.KeepAlive(x) 47 } 48 { 49 var x PtrScalar 50 verifyGCInfo(t, "stack PtrScalar", &x, infoPtrScalar) 51 runtime.KeepAlive(x) 52 } 53 { 54 var x BigStruct 55 verifyGCInfo(t, "stack BigStruct", &x, infoBigStruct()) 56 runtime.KeepAlive(x) 57 } 58 { 59 var x string 60 verifyGCInfo(t, "stack string", &x, infoString) 61 runtime.KeepAlive(x) 62 } 63 { 64 var x []string 65 verifyGCInfo(t, "stack slice", &x, infoSlice) 66 runtime.KeepAlive(x) 67 } 68 { 69 var x interface{} 70 verifyGCInfo(t, "stack eface", &x, infoEface) 71 runtime.KeepAlive(x) 72 } 73 { 74 var x Iface 75 verifyGCInfo(t, "stack iface", &x, infoIface) 76 runtime.KeepAlive(x) 77 } 78 79 for i := 0; i < 10; i++ { 80 verifyGCInfo(t, "heap Ptr", escape(new(Ptr)), trimDead(padDead(infoPtr))) 81 verifyGCInfo(t, "heap PtrSlice", escape(&make([]*byte, 10)[0]), trimDead(infoPtr10)) 82 verifyGCInfo(t, "heap ScalarPtr", escape(new(ScalarPtr)), trimDead(infoScalarPtr)) 83 verifyGCInfo(t, "heap ScalarPtrSlice", escape(&make([]ScalarPtr, 4)[0]), trimDead(infoScalarPtr4)) 84 verifyGCInfo(t, "heap PtrScalar", escape(new(PtrScalar)), trimDead(infoPtrScalar)) 85 verifyGCInfo(t, "heap BigStruct", escape(new(BigStruct)), trimDead(infoBigStruct())) 86 verifyGCInfo(t, "heap string", escape(new(string)), trimDead(infoString)) 87 verifyGCInfo(t, "heap eface", escape(new(interface{})), trimDead(infoEface)) 88 verifyGCInfo(t, "heap iface", escape(new(Iface)), trimDead(infoIface)) 89 } 90 } 91 92 func verifyGCInfo(t *testing.T, name string, p interface{}, mask0 []byte) { 93 mask := runtime.GCMask(p) 94 if !bytes.Equal(mask, mask0) { 95 t.Errorf("bad GC program for %v:\nwant %+v\ngot %+v", name, mask0, mask) 96 return 97 } 98 } 99 100 func padDead(mask []byte) []byte { 101 // Because the dead bit isn't encoded in the second word, 102 // and because on 32-bit systems a one-word allocation 103 // uses a two-word block, the pointer info for a one-word 104 // object needs to be expanded to include an extra scalar 105 // on 32-bit systems to match the heap bitmap. 106 if runtime.PtrSize == 4 && len(mask) == 1 { 107 return []byte{mask[0], 0} 108 } 109 return mask 110 } 111 112 func trimDead(mask []byte) []byte { 113 for len(mask) > 2 && mask[len(mask)-1] == typeScalar { 114 mask = mask[:len(mask)-1] 115 } 116 if len(mask) == 2 && mask[0] == typeScalar && mask[1] == typeScalar { 117 mask = mask[:0] 118 } 119 return mask 120 } 121 122 var gcinfoSink interface{} 123 124 func escape(p interface{}) interface{} { 125 gcinfoSink = p 126 return p 127 } 128 129 var infoPtr = []byte{typePointer} 130 131 type Ptr struct { 132 *byte 133 } 134 135 var infoPtr10 = []byte{typePointer, typePointer, typePointer, typePointer, typePointer, typePointer, typePointer, typePointer, typePointer, typePointer} 136 137 type ScalarPtr struct { 138 q int 139 w *int 140 e int 141 r *int 142 t int 143 y *int 144 } 145 146 var infoScalarPtr = []byte{typeScalar, typePointer, typeScalar, typePointer, typeScalar, typePointer} 147 148 var infoScalarPtr4 = append(append(append(append([]byte(nil), infoScalarPtr...), infoScalarPtr...), infoScalarPtr...), infoScalarPtr...) 149 150 type PtrScalar struct { 151 q *int 152 w int 153 e *int 154 r int 155 t *int 156 y int 157 } 158 159 var infoPtrScalar = []byte{typePointer, typeScalar, typePointer, typeScalar, typePointer, typeScalar} 160 161 type BigStruct struct { 162 q *int 163 w byte 164 e [17]byte 165 r []byte 166 t int 167 y uint16 168 u uint64 169 i string 170 } 171 172 func infoBigStruct() []byte { 173 switch runtime.GOARCH { 174 case "386", "arm", "mips", "mipsle": 175 return []byte{ 176 typePointer, // q *int 177 typeScalar, typeScalar, typeScalar, typeScalar, typeScalar, // w byte; e [17]byte 178 typePointer, typeScalar, typeScalar, // r []byte 179 typeScalar, typeScalar, typeScalar, typeScalar, // t int; y uint16; u uint64 180 typePointer, typeScalar, // i string 181 } 182 case "arm64", "amd64", "mips64", "mips64le", "ppc64", "ppc64le", "s390x", "wasm": 183 return []byte{ 184 typePointer, // q *int 185 typeScalar, typeScalar, typeScalar, // w byte; e [17]byte 186 typePointer, typeScalar, typeScalar, // r []byte 187 typeScalar, typeScalar, typeScalar, // t int; y uint16; u uint64 188 typePointer, typeScalar, // i string 189 } 190 case "amd64p32": 191 return []byte{ 192 typePointer, // q *int 193 typeScalar, typeScalar, typeScalar, typeScalar, typeScalar, // w byte; e [17]byte 194 typePointer, typeScalar, typeScalar, // r []byte 195 typeScalar, typeScalar, typeScalar, typeScalar, typeScalar, // t int; y uint16; u uint64 196 typePointer, typeScalar, // i string 197 } 198 default: 199 panic("unknown arch") 200 } 201 } 202 203 type Iface interface { 204 f() 205 } 206 207 type IfaceImpl int 208 209 func (IfaceImpl) f() { 210 } 211 212 var ( 213 // BSS 214 bssPtr Ptr 215 bssScalarPtr ScalarPtr 216 bssPtrScalar PtrScalar 217 bssBigStruct BigStruct 218 bssString string 219 bssSlice []string 220 bssEface interface{} 221 bssIface Iface 222 223 // DATA 224 dataPtr = Ptr{new(byte)} 225 dataScalarPtr = ScalarPtr{q: 1} 226 dataPtrScalar = PtrScalar{w: 1} 227 dataBigStruct = BigStruct{w: 1} 228 dataString = "foo" 229 dataSlice = []string{"foo"} 230 dataEface interface{} = 42 231 dataIface Iface = IfaceImpl(42) 232 233 infoString = []byte{typePointer, typeScalar} 234 infoSlice = []byte{typePointer, typeScalar, typeScalar} 235 infoEface = []byte{typeScalar, typePointer} 236 infoIface = []byte{typeScalar, typePointer} 237 )