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 any 48 e_ any 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 BenchmarkConvT2EByteSized(b *testing.B) { 99 b.Run("bool", func(b *testing.B) { 100 for i := 0; i < b.N; i++ { 101 e = yes 102 } 103 }) 104 b.Run("uint8", func(b *testing.B) { 105 for i := 0; i < b.N; i++ { 106 e = eight8 107 } 108 }) 109} 110 111func BenchmarkConvT2ESmall(b *testing.B) { 112 for i := 0; i < b.N; i++ { 113 e = ts 114 } 115} 116 117func BenchmarkConvT2EUintptr(b *testing.B) { 118 for i := 0; i < b.N; i++ { 119 e = tm 120 } 121} 122 123func BenchmarkConvT2ELarge(b *testing.B) { 124 for i := 0; i < b.N; i++ { 125 e = tl 126 } 127} 128 129func BenchmarkConvT2ISmall(b *testing.B) { 130 for i := 0; i < b.N; i++ { 131 i1 = ts 132 } 133} 134 135func BenchmarkConvT2IUintptr(b *testing.B) { 136 for i := 0; i < b.N; i++ { 137 i1 = tm 138 } 139} 140 141func BenchmarkConvT2ILarge(b *testing.B) { 142 for i := 0; i < b.N; i++ { 143 i1 = tl 144 } 145} 146 147func BenchmarkConvI2E(b *testing.B) { 148 i2 = tm 149 for i := 0; i < b.N; i++ { 150 e = i2 151 } 152} 153 154func BenchmarkConvI2I(b *testing.B) { 155 i2 = tm 156 for i := 0; i < b.N; i++ { 157 i1 = i2 158 } 159} 160 161func BenchmarkAssertE2T(b *testing.B) { 162 e = tm 163 for i := 0; i < b.N; i++ { 164 tm = e.(TM) 165 } 166} 167 168func BenchmarkAssertE2TLarge(b *testing.B) { 169 e = tl 170 for i := 0; i < b.N; i++ { 171 tl = e.(TL) 172 } 173} 174 175func BenchmarkAssertE2I(b *testing.B) { 176 e = tm 177 for i := 0; i < b.N; i++ { 178 i1 = e.(I1) 179 } 180} 181 182func BenchmarkAssertI2T(b *testing.B) { 183 i1 = tm 184 for i := 0; i < b.N; i++ { 185 tm = i1.(TM) 186 } 187} 188 189func BenchmarkAssertI2I(b *testing.B) { 190 i1 = tm 191 for i := 0; i < b.N; i++ { 192 i2 = i1.(I2) 193 } 194} 195 196func BenchmarkAssertI2E(b *testing.B) { 197 i1 = tm 198 for i := 0; i < b.N; i++ { 199 e = i1.(any) 200 } 201} 202 203func BenchmarkAssertE2E(b *testing.B) { 204 e = tm 205 for i := 0; i < b.N; i++ { 206 e_ = e 207 } 208} 209 210func BenchmarkAssertE2T2(b *testing.B) { 211 e = tm 212 for i := 0; i < b.N; i++ { 213 tm, ok = e.(TM) 214 } 215} 216 217func BenchmarkAssertE2T2Blank(b *testing.B) { 218 e = tm 219 for i := 0; i < b.N; i++ { 220 _, ok = e.(TM) 221 } 222} 223 224func BenchmarkAssertI2E2(b *testing.B) { 225 i1 = tm 226 for i := 0; i < b.N; i++ { 227 e, ok = i1.(any) 228 } 229} 230 231func BenchmarkAssertI2E2Blank(b *testing.B) { 232 i1 = tm 233 for i := 0; i < b.N; i++ { 234 _, ok = i1.(any) 235 } 236} 237 238func BenchmarkAssertE2E2(b *testing.B) { 239 e = tm 240 for i := 0; i < b.N; i++ { 241 e_, ok = e.(any) 242 } 243} 244 245func BenchmarkAssertE2E2Blank(b *testing.B) { 246 e = tm 247 for i := 0; i < b.N; i++ { 248 _, ok = e.(any) 249 } 250} 251 252func TestNonEscapingConvT2E(t *testing.T) { 253 m := make(map[any]bool) 254 m[42] = true 255 if !m[42] { 256 t.Fatalf("42 is not present in the map") 257 } 258 if m[0] { 259 t.Fatalf("0 is present in the map") 260 } 261 262 n := testing.AllocsPerRun(1000, func() { 263 if m[0] { 264 t.Fatalf("0 is present in the map") 265 } 266 }) 267 if n != 0 { 268 t.Fatalf("want 0 allocs, got %v", n) 269 } 270} 271 272func TestNonEscapingConvT2I(t *testing.T) { 273 m := make(map[I1]bool) 274 m[TM(42)] = true 275 if !m[TM(42)] { 276 t.Fatalf("42 is not present in the map") 277 } 278 if m[TM(0)] { 279 t.Fatalf("0 is present in the map") 280 } 281 282 n := testing.AllocsPerRun(1000, func() { 283 if m[TM(0)] { 284 t.Fatalf("0 is present in the map") 285 } 286 }) 287 if n != 0 { 288 t.Fatalf("want 0 allocs, got %v", n) 289 } 290} 291 292func TestZeroConvT2x(t *testing.T) { 293 tests := []struct { 294 name string 295 fn func() 296 }{ 297 {name: "E8", fn: func() { e = eight8 }}, // any byte-sized value does not allocate 298 {name: "E16", fn: func() { e = zero16 }}, // zero values do not allocate 299 {name: "E32", fn: func() { e = zero32 }}, 300 {name: "E64", fn: func() { e = zero64 }}, 301 {name: "Estr", fn: func() { e = zerostr }}, 302 {name: "Eslice", fn: func() { e = zeroslice }}, 303 {name: "Econstflt", fn: func() { e = 99.0 }}, // constants do not allocate 304 {name: "Econststr", fn: func() { e = "change" }}, 305 {name: "I8", fn: func() { i1 = eight8I }}, 306 {name: "I16", fn: func() { i1 = zero16I }}, 307 {name: "I32", fn: func() { i1 = zero32I }}, 308 {name: "I64", fn: func() { i1 = zero64I }}, 309 {name: "Istr", fn: func() { i1 = zerostrI }}, 310 {name: "Islice", fn: func() { i1 = zerosliceI }}, 311 } 312 313 for _, test := range tests { 314 t.Run(test.name, func(t *testing.T) { 315 n := testing.AllocsPerRun(1000, test.fn) 316 if n != 0 { 317 t.Errorf("want zero allocs, got %v", n) 318 } 319 }) 320 } 321} 322 323var ( 324 eight8 uint8 = 8 325 eight8I T8 = 8 326 yes bool = true 327 328 zero16 uint16 = 0 329 zero16I T16 = 0 330 one16 uint16 = 1 331 thousand16 uint16 = 1000 332 333 zero32 uint32 = 0 334 zero32I T32 = 0 335 one32 uint32 = 1 336 thousand32 uint32 = 1000 337 338 zero64 uint64 = 0 339 zero64I T64 = 0 340 one64 uint64 = 1 341 thousand64 uint64 = 1000 342 343 zerostr string = "" 344 zerostrI Tstr = "" 345 nzstr string = "abc" 346 347 zeroslice []byte = nil 348 zerosliceI Tslice = nil 349 nzslice []byte = []byte("abc") 350 351 zerobig [512]byte 352 nzbig [512]byte = [512]byte{511: 1} 353) 354 355func BenchmarkConvT2Ezero(b *testing.B) { 356 b.Run("zero", func(b *testing.B) { 357 b.Run("16", func(b *testing.B) { 358 for i := 0; i < b.N; i++ { 359 e = zero16 360 } 361 }) 362 b.Run("32", func(b *testing.B) { 363 for i := 0; i < b.N; i++ { 364 e = zero32 365 } 366 }) 367 b.Run("64", func(b *testing.B) { 368 for i := 0; i < b.N; i++ { 369 e = zero64 370 } 371 }) 372 b.Run("str", func(b *testing.B) { 373 for i := 0; i < b.N; i++ { 374 e = zerostr 375 } 376 }) 377 b.Run("slice", func(b *testing.B) { 378 for i := 0; i < b.N; i++ { 379 e = zeroslice 380 } 381 }) 382 b.Run("big", func(b *testing.B) { 383 for i := 0; i < b.N; i++ { 384 e = zerobig 385 } 386 }) 387 }) 388 b.Run("nonzero", func(b *testing.B) { 389 b.Run("str", func(b *testing.B) { 390 for i := 0; i < b.N; i++ { 391 e = nzstr 392 } 393 }) 394 b.Run("slice", func(b *testing.B) { 395 for i := 0; i < b.N; i++ { 396 e = nzslice 397 } 398 }) 399 b.Run("big", func(b *testing.B) { 400 for i := 0; i < b.N; i++ { 401 e = nzbig 402 } 403 }) 404 }) 405 b.Run("smallint", func(b *testing.B) { 406 b.Run("16", func(b *testing.B) { 407 for i := 0; i < b.N; i++ { 408 e = one16 409 } 410 }) 411 b.Run("32", func(b *testing.B) { 412 for i := 0; i < b.N; i++ { 413 e = one32 414 } 415 }) 416 b.Run("64", func(b *testing.B) { 417 for i := 0; i < b.N; i++ { 418 e = one64 419 } 420 }) 421 }) 422 b.Run("largeint", func(b *testing.B) { 423 b.Run("16", func(b *testing.B) { 424 for i := 0; i < b.N; i++ { 425 e = thousand16 426 } 427 }) 428 b.Run("32", func(b *testing.B) { 429 for i := 0; i < b.N; i++ { 430 e = thousand32 431 } 432 }) 433 b.Run("64", func(b *testing.B) { 434 for i := 0; i < b.N; i++ { 435 e = thousand64 436 } 437 }) 438 }) 439} 440