1// Copyright 2012 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 5package runtime_test 6 7import ( 8 "runtime" 9 "testing" 10) 11 12type I1 interface { 13 Method1() 14} 15 16type I2 interface { 17 Method1() 18 Method2() 19} 20 21type TS uint16 22type TM uintptr 23type TL [2]uintptr 24 25func (TS) Method1() {} 26func (TS) Method2() {} 27func (TM) Method1() {} 28func (TM) Method2() {} 29func (TL) Method1() {} 30func (TL) Method2() {} 31 32type T8 uint8 33type T16 uint16 34type T32 uint32 35type T64 uint64 36type Tstr string 37type Tslice []byte 38 39func (T8) Method1() {} 40func (T16) Method1() {} 41func (T32) Method1() {} 42func (T64) Method1() {} 43func (Tstr) Method1() {} 44func (Tslice) Method1() {} 45 46var ( 47 e interface{} 48 e_ interface{} 49 i1 I1 50 i2 I2 51 ts TS 52 tm TM 53 tl TL 54 ok bool 55) 56 57// Issue 9370 58func TestCmpIfaceConcreteAlloc(t *testing.T) { 59 if runtime.Compiler != "gc" { 60 t.Skip("skipping on non-gc compiler") 61 } 62 63 n := testing.AllocsPerRun(1, func() { 64 _ = e == ts 65 _ = i1 == ts 66 _ = e == 1 67 }) 68 69 if n > 0 { 70 t.Fatalf("iface cmp allocs=%v; want 0", n) 71 } 72} 73 74func BenchmarkEqEfaceConcrete(b *testing.B) { 75 for i := 0; i < b.N; i++ { 76 _ = e == ts 77 } 78} 79 80func BenchmarkEqIfaceConcrete(b *testing.B) { 81 for i := 0; i < b.N; i++ { 82 _ = i1 == ts 83 } 84} 85 86func BenchmarkNeEfaceConcrete(b *testing.B) { 87 for i := 0; i < b.N; i++ { 88 _ = e != ts 89 } 90} 91 92func BenchmarkNeIfaceConcrete(b *testing.B) { 93 for i := 0; i < b.N; i++ { 94 _ = i1 != ts 95 } 96} 97 98func BenchmarkConvT2ESmall(b *testing.B) { 99 for i := 0; i < b.N; i++ { 100 e = ts 101 } 102} 103 104func BenchmarkConvT2EUintptr(b *testing.B) { 105 for i := 0; i < b.N; i++ { 106 e = tm 107 } 108} 109 110func BenchmarkConvT2ELarge(b *testing.B) { 111 for i := 0; i < b.N; i++ { 112 e = tl 113 } 114} 115 116func BenchmarkConvT2ISmall(b *testing.B) { 117 for i := 0; i < b.N; i++ { 118 i1 = ts 119 } 120} 121 122func BenchmarkConvT2IUintptr(b *testing.B) { 123 for i := 0; i < b.N; i++ { 124 i1 = tm 125 } 126} 127 128func BenchmarkConvT2ILarge(b *testing.B) { 129 for i := 0; i < b.N; i++ { 130 i1 = tl 131 } 132} 133 134func BenchmarkConvI2E(b *testing.B) { 135 i2 = tm 136 for i := 0; i < b.N; i++ { 137 e = i2 138 } 139} 140 141func BenchmarkConvI2I(b *testing.B) { 142 i2 = tm 143 for i := 0; i < b.N; i++ { 144 i1 = i2 145 } 146} 147 148func BenchmarkAssertE2T(b *testing.B) { 149 e = tm 150 for i := 0; i < b.N; i++ { 151 tm = e.(TM) 152 } 153} 154 155func BenchmarkAssertE2TLarge(b *testing.B) { 156 e = tl 157 for i := 0; i < b.N; i++ { 158 tl = e.(TL) 159 } 160} 161 162func BenchmarkAssertE2I(b *testing.B) { 163 e = tm 164 for i := 0; i < b.N; i++ { 165 i1 = e.(I1) 166 } 167} 168 169func BenchmarkAssertI2T(b *testing.B) { 170 i1 = tm 171 for i := 0; i < b.N; i++ { 172 tm = i1.(TM) 173 } 174} 175 176func BenchmarkAssertI2I(b *testing.B) { 177 i1 = tm 178 for i := 0; i < b.N; i++ { 179 i2 = i1.(I2) 180 } 181} 182 183func BenchmarkAssertI2E(b *testing.B) { 184 i1 = tm 185 for i := 0; i < b.N; i++ { 186 e = i1.(interface{}) 187 } 188} 189 190func BenchmarkAssertE2E(b *testing.B) { 191 e = tm 192 for i := 0; i < b.N; i++ { 193 e_ = e 194 } 195} 196 197func BenchmarkAssertE2T2(b *testing.B) { 198 e = tm 199 for i := 0; i < b.N; i++ { 200 tm, ok = e.(TM) 201 } 202} 203 204func BenchmarkAssertE2T2Blank(b *testing.B) { 205 e = tm 206 for i := 0; i < b.N; i++ { 207 _, ok = e.(TM) 208 } 209} 210 211func BenchmarkAssertI2E2(b *testing.B) { 212 i1 = tm 213 for i := 0; i < b.N; i++ { 214 e, ok = i1.(interface{}) 215 } 216} 217 218func BenchmarkAssertI2E2Blank(b *testing.B) { 219 i1 = tm 220 for i := 0; i < b.N; i++ { 221 _, ok = i1.(interface{}) 222 } 223} 224 225func BenchmarkAssertE2E2(b *testing.B) { 226 e = tm 227 for i := 0; i < b.N; i++ { 228 e_, ok = e.(interface{}) 229 } 230} 231 232func BenchmarkAssertE2E2Blank(b *testing.B) { 233 e = tm 234 for i := 0; i < b.N; i++ { 235 _, ok = e.(interface{}) 236 } 237} 238 239func TestNonEscapingConvT2E(t *testing.T) { 240 if runtime.Compiler == "gccgo" { 241 t.Skip("does not work on gccgo without better escape analysis") 242 } 243 244 m := make(map[interface{}]bool) 245 m[42] = true 246 if !m[42] { 247 t.Fatalf("42 is not present in the map") 248 } 249 if m[0] { 250 t.Fatalf("0 is present in the map") 251 } 252 253 n := testing.AllocsPerRun(1000, func() { 254 if m[0] { 255 t.Fatalf("0 is present in the map") 256 } 257 }) 258 if n != 0 { 259 t.Fatalf("want 0 allocs, got %v", n) 260 } 261} 262 263func TestNonEscapingConvT2I(t *testing.T) { 264 if runtime.Compiler == "gccgo" { 265 t.Skip("does not work on gccgo without better escape analysis") 266 } 267 268 m := make(map[I1]bool) 269 m[TM(42)] = true 270 if !m[TM(42)] { 271 t.Fatalf("42 is not present in the map") 272 } 273 if m[TM(0)] { 274 t.Fatalf("0 is present in the map") 275 } 276 277 n := testing.AllocsPerRun(1000, func() { 278 if m[TM(0)] { 279 t.Fatalf("0 is present in the map") 280 } 281 }) 282 if n != 0 { 283 t.Fatalf("want 0 allocs, got %v", n) 284 } 285} 286 287func TestZeroConvT2x(t *testing.T) { 288 if runtime.Compiler == "gccgo" { 289 t.Skip("does not work on gccgo without better escape analysis") 290 } 291 292 tests := []struct { 293 name string 294 fn func() 295 }{ 296 {name: "E8", fn: func() { e = eight8 }}, // any byte-sized value does not allocate 297 {name: "E16", fn: func() { e = zero16 }}, // zero values do not allocate 298 {name: "E32", fn: func() { e = zero32 }}, 299 {name: "E64", fn: func() { e = zero64 }}, 300 {name: "Estr", fn: func() { e = zerostr }}, 301 {name: "Eslice", fn: func() { e = zeroslice }}, 302 {name: "Econstflt", fn: func() { e = 99.0 }}, // constants do not allocate 303 {name: "Econststr", fn: func() { e = "change" }}, 304 {name: "I8", fn: func() { i1 = eight8I }}, 305 {name: "I16", fn: func() { i1 = zero16I }}, 306 {name: "I32", fn: func() { i1 = zero32I }}, 307 {name: "I64", fn: func() { i1 = zero64I }}, 308 {name: "Istr", fn: func() { i1 = zerostrI }}, 309 {name: "Islice", fn: func() { i1 = zerosliceI }}, 310 } 311 312 for _, test := range tests { 313 t.Run(test.name, func(t *testing.T) { 314 n := testing.AllocsPerRun(1000, test.fn) 315 if n != 0 { 316 t.Errorf("want zero allocs, got %v", n) 317 } 318 }) 319 } 320} 321 322var ( 323 eight8 uint8 = 8 324 eight8I T8 = 8 325 326 zero16 uint16 = 0 327 zero16I T16 = 0 328 one16 uint16 = 1 329 330 zero32 uint32 = 0 331 zero32I T32 = 0 332 one32 uint32 = 1 333 334 zero64 uint64 = 0 335 zero64I T64 = 0 336 one64 uint64 = 1 337 338 zerostr string = "" 339 zerostrI Tstr = "" 340 nzstr string = "abc" 341 342 zeroslice []byte = nil 343 zerosliceI Tslice = nil 344 nzslice []byte = []byte("abc") 345 346 zerobig [512]byte 347 nzbig [512]byte = [512]byte{511: 1} 348) 349 350func BenchmarkConvT2Ezero(b *testing.B) { 351 b.Run("zero", func(b *testing.B) { 352 b.Run("16", func(b *testing.B) { 353 for i := 0; i < b.N; i++ { 354 e = zero16 355 } 356 }) 357 b.Run("32", func(b *testing.B) { 358 for i := 0; i < b.N; i++ { 359 e = zero32 360 } 361 }) 362 b.Run("64", func(b *testing.B) { 363 for i := 0; i < b.N; i++ { 364 e = zero64 365 } 366 }) 367 b.Run("str", func(b *testing.B) { 368 for i := 0; i < b.N; i++ { 369 e = zerostr 370 } 371 }) 372 b.Run("slice", func(b *testing.B) { 373 for i := 0; i < b.N; i++ { 374 e = zeroslice 375 } 376 }) 377 b.Run("big", func(b *testing.B) { 378 for i := 0; i < b.N; i++ { 379 e = zerobig 380 } 381 }) 382 }) 383 b.Run("nonzero", func(b *testing.B) { 384 b.Run("16", func(b *testing.B) { 385 for i := 0; i < b.N; i++ { 386 e = one16 387 } 388 }) 389 b.Run("32", func(b *testing.B) { 390 for i := 0; i < b.N; i++ { 391 e = one32 392 } 393 }) 394 b.Run("64", func(b *testing.B) { 395 for i := 0; i < b.N; i++ { 396 e = one64 397 } 398 }) 399 b.Run("str", func(b *testing.B) { 400 for i := 0; i < b.N; i++ { 401 e = nzstr 402 } 403 }) 404 b.Run("slice", func(b *testing.B) { 405 for i := 0; i < b.N; i++ { 406 e = nzslice 407 } 408 }) 409 b.Run("big", func(b *testing.B) { 410 for i := 0; i < b.N; i++ { 411 e = nzbig 412 } 413 }) 414 }) 415} 416