diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-16 19:23:18 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-16 19:23:18 +0000 |
commit | 43a123c1ae6613b3efeed291fa552ecd909d3acf (patch) | |
tree | fd92518b7024bc74031f78a1cf9e454b65e73665 /src/runtime/iface_test.go | |
parent | Initial commit. (diff) | |
download | golang-1.20-43a123c1ae6613b3efeed291fa552ecd909d3acf.tar.xz golang-1.20-43a123c1ae6613b3efeed291fa552ecd909d3acf.zip |
Adding upstream version 1.20.14.upstream/1.20.14upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/runtime/iface_test.go')
-rw-r--r-- | src/runtime/iface_test.go | 439 |
1 files changed, 439 insertions, 0 deletions
diff --git a/src/runtime/iface_test.go b/src/runtime/iface_test.go new file mode 100644 index 0000000..06f6eeb --- /dev/null +++ b/src/runtime/iface_test.go @@ -0,0 +1,439 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package runtime_test + +import ( + "runtime" + "testing" +) + +type I1 interface { + Method1() +} + +type I2 interface { + Method1() + Method2() +} + +type TS uint16 +type TM uintptr +type TL [2]uintptr + +func (TS) Method1() {} +func (TS) Method2() {} +func (TM) Method1() {} +func (TM) Method2() {} +func (TL) Method1() {} +func (TL) Method2() {} + +type T8 uint8 +type T16 uint16 +type T32 uint32 +type T64 uint64 +type Tstr string +type Tslice []byte + +func (T8) Method1() {} +func (T16) Method1() {} +func (T32) Method1() {} +func (T64) Method1() {} +func (Tstr) Method1() {} +func (Tslice) Method1() {} + +var ( + e any + e_ any + i1 I1 + i2 I2 + ts TS + tm TM + tl TL + ok bool +) + +// Issue 9370 +func TestCmpIfaceConcreteAlloc(t *testing.T) { + if runtime.Compiler != "gc" { + t.Skip("skipping on non-gc compiler") + } + + n := testing.AllocsPerRun(1, func() { + _ = e == ts + _ = i1 == ts + _ = e == 1 + }) + + if n > 0 { + t.Fatalf("iface cmp allocs=%v; want 0", n) + } +} + +func BenchmarkEqEfaceConcrete(b *testing.B) { + for i := 0; i < b.N; i++ { + _ = e == ts + } +} + +func BenchmarkEqIfaceConcrete(b *testing.B) { + for i := 0; i < b.N; i++ { + _ = i1 == ts + } +} + +func BenchmarkNeEfaceConcrete(b *testing.B) { + for i := 0; i < b.N; i++ { + _ = e != ts + } +} + +func BenchmarkNeIfaceConcrete(b *testing.B) { + for i := 0; i < b.N; i++ { + _ = i1 != ts + } +} + +func BenchmarkConvT2EByteSized(b *testing.B) { + b.Run("bool", func(b *testing.B) { + for i := 0; i < b.N; i++ { + e = yes + } + }) + b.Run("uint8", func(b *testing.B) { + for i := 0; i < b.N; i++ { + e = eight8 + } + }) +} + +func BenchmarkConvT2ESmall(b *testing.B) { + for i := 0; i < b.N; i++ { + e = ts + } +} + +func BenchmarkConvT2EUintptr(b *testing.B) { + for i := 0; i < b.N; i++ { + e = tm + } +} + +func BenchmarkConvT2ELarge(b *testing.B) { + for i := 0; i < b.N; i++ { + e = tl + } +} + +func BenchmarkConvT2ISmall(b *testing.B) { + for i := 0; i < b.N; i++ { + i1 = ts + } +} + +func BenchmarkConvT2IUintptr(b *testing.B) { + for i := 0; i < b.N; i++ { + i1 = tm + } +} + +func BenchmarkConvT2ILarge(b *testing.B) { + for i := 0; i < b.N; i++ { + i1 = tl + } +} + +func BenchmarkConvI2E(b *testing.B) { + i2 = tm + for i := 0; i < b.N; i++ { + e = i2 + } +} + +func BenchmarkConvI2I(b *testing.B) { + i2 = tm + for i := 0; i < b.N; i++ { + i1 = i2 + } +} + +func BenchmarkAssertE2T(b *testing.B) { + e = tm + for i := 0; i < b.N; i++ { + tm = e.(TM) + } +} + +func BenchmarkAssertE2TLarge(b *testing.B) { + e = tl + for i := 0; i < b.N; i++ { + tl = e.(TL) + } +} + +func BenchmarkAssertE2I(b *testing.B) { + e = tm + for i := 0; i < b.N; i++ { + i1 = e.(I1) + } +} + +func BenchmarkAssertI2T(b *testing.B) { + i1 = tm + for i := 0; i < b.N; i++ { + tm = i1.(TM) + } +} + +func BenchmarkAssertI2I(b *testing.B) { + i1 = tm + for i := 0; i < b.N; i++ { + i2 = i1.(I2) + } +} + +func BenchmarkAssertI2E(b *testing.B) { + i1 = tm + for i := 0; i < b.N; i++ { + e = i1.(any) + } +} + +func BenchmarkAssertE2E(b *testing.B) { + e = tm + for i := 0; i < b.N; i++ { + e_ = e + } +} + +func BenchmarkAssertE2T2(b *testing.B) { + e = tm + for i := 0; i < b.N; i++ { + tm, ok = e.(TM) + } +} + +func BenchmarkAssertE2T2Blank(b *testing.B) { + e = tm + for i := 0; i < b.N; i++ { + _, ok = e.(TM) + } +} + +func BenchmarkAssertI2E2(b *testing.B) { + i1 = tm + for i := 0; i < b.N; i++ { + e, ok = i1.(any) + } +} + +func BenchmarkAssertI2E2Blank(b *testing.B) { + i1 = tm + for i := 0; i < b.N; i++ { + _, ok = i1.(any) + } +} + +func BenchmarkAssertE2E2(b *testing.B) { + e = tm + for i := 0; i < b.N; i++ { + e_, ok = e.(any) + } +} + +func BenchmarkAssertE2E2Blank(b *testing.B) { + e = tm + for i := 0; i < b.N; i++ { + _, ok = e.(any) + } +} + +func TestNonEscapingConvT2E(t *testing.T) { + m := make(map[any]bool) + m[42] = true + if !m[42] { + t.Fatalf("42 is not present in the map") + } + if m[0] { + t.Fatalf("0 is present in the map") + } + + n := testing.AllocsPerRun(1000, func() { + if m[0] { + t.Fatalf("0 is present in the map") + } + }) + if n != 0 { + t.Fatalf("want 0 allocs, got %v", n) + } +} + +func TestNonEscapingConvT2I(t *testing.T) { + m := make(map[I1]bool) + m[TM(42)] = true + if !m[TM(42)] { + t.Fatalf("42 is not present in the map") + } + if m[TM(0)] { + t.Fatalf("0 is present in the map") + } + + n := testing.AllocsPerRun(1000, func() { + if m[TM(0)] { + t.Fatalf("0 is present in the map") + } + }) + if n != 0 { + t.Fatalf("want 0 allocs, got %v", n) + } +} + +func TestZeroConvT2x(t *testing.T) { + tests := []struct { + name string + fn func() + }{ + {name: "E8", fn: func() { e = eight8 }}, // any byte-sized value does not allocate + {name: "E16", fn: func() { e = zero16 }}, // zero values do not allocate + {name: "E32", fn: func() { e = zero32 }}, + {name: "E64", fn: func() { e = zero64 }}, + {name: "Estr", fn: func() { e = zerostr }}, + {name: "Eslice", fn: func() { e = zeroslice }}, + {name: "Econstflt", fn: func() { e = 99.0 }}, // constants do not allocate + {name: "Econststr", fn: func() { e = "change" }}, + {name: "I8", fn: func() { i1 = eight8I }}, + {name: "I16", fn: func() { i1 = zero16I }}, + {name: "I32", fn: func() { i1 = zero32I }}, + {name: "I64", fn: func() { i1 = zero64I }}, + {name: "Istr", fn: func() { i1 = zerostrI }}, + {name: "Islice", fn: func() { i1 = zerosliceI }}, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + n := testing.AllocsPerRun(1000, test.fn) + if n != 0 { + t.Errorf("want zero allocs, got %v", n) + } + }) + } +} + +var ( + eight8 uint8 = 8 + eight8I T8 = 8 + yes bool = true + + zero16 uint16 = 0 + zero16I T16 = 0 + one16 uint16 = 1 + thousand16 uint16 = 1000 + + zero32 uint32 = 0 + zero32I T32 = 0 + one32 uint32 = 1 + thousand32 uint32 = 1000 + + zero64 uint64 = 0 + zero64I T64 = 0 + one64 uint64 = 1 + thousand64 uint64 = 1000 + + zerostr string = "" + zerostrI Tstr = "" + nzstr string = "abc" + + zeroslice []byte = nil + zerosliceI Tslice = nil + nzslice []byte = []byte("abc") + + zerobig [512]byte + nzbig [512]byte = [512]byte{511: 1} +) + +func BenchmarkConvT2Ezero(b *testing.B) { + b.Run("zero", func(b *testing.B) { + b.Run("16", func(b *testing.B) { + for i := 0; i < b.N; i++ { + e = zero16 + } + }) + b.Run("32", func(b *testing.B) { + for i := 0; i < b.N; i++ { + e = zero32 + } + }) + b.Run("64", func(b *testing.B) { + for i := 0; i < b.N; i++ { + e = zero64 + } + }) + b.Run("str", func(b *testing.B) { + for i := 0; i < b.N; i++ { + e = zerostr + } + }) + b.Run("slice", func(b *testing.B) { + for i := 0; i < b.N; i++ { + e = zeroslice + } + }) + b.Run("big", func(b *testing.B) { + for i := 0; i < b.N; i++ { + e = zerobig + } + }) + }) + b.Run("nonzero", func(b *testing.B) { + b.Run("str", func(b *testing.B) { + for i := 0; i < b.N; i++ { + e = nzstr + } + }) + b.Run("slice", func(b *testing.B) { + for i := 0; i < b.N; i++ { + e = nzslice + } + }) + b.Run("big", func(b *testing.B) { + for i := 0; i < b.N; i++ { + e = nzbig + } + }) + }) + b.Run("smallint", func(b *testing.B) { + b.Run("16", func(b *testing.B) { + for i := 0; i < b.N; i++ { + e = one16 + } + }) + b.Run("32", func(b *testing.B) { + for i := 0; i < b.N; i++ { + e = one32 + } + }) + b.Run("64", func(b *testing.B) { + for i := 0; i < b.N; i++ { + e = one64 + } + }) + }) + b.Run("largeint", func(b *testing.B) { + b.Run("16", func(b *testing.B) { + for i := 0; i < b.N; i++ { + e = thousand16 + } + }) + b.Run("32", func(b *testing.B) { + for i := 0; i < b.N; i++ { + e = thousand32 + } + }) + b.Run("64", func(b *testing.B) { + for i := 0; i < b.N; i++ { + e = thousand64 + } + }) + }) +} |