blob: 6d8f8614d985070fcb9cd3774b390498c5475472 [file] [log] [blame]
Colin Cross7bb052a2015-02-03 12:59:37 -08001// 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 (
Dan Willemsen6ff23252015-09-15 13:49:18 -07008 "runtime"
Colin Cross7bb052a2015-02-03 12:59:37 -08009 "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
Dan Willemsenc78f7142017-07-26 13:08:14 -070032type 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
Colin Cross7bb052a2015-02-03 12:59:37 -080046var (
47 e interface{}
48 e_ interface{}
49 i1 I1
50 i2 I2
51 ts TS
52 tm TM
53 tl TL
Dan Willemsen6ff23252015-09-15 13:49:18 -070054 ok bool
Colin Cross7bb052a2015-02-03 12:59:37 -080055)
56
Dan Willemsen6ff23252015-09-15 13:49:18 -070057// 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
Colin Cross7bb052a2015-02-03 12:59:37 -080098func 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}
Dan Willemsen6ff23252015-09-15 13:49:18 -0700196
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 m := make(map[interface{}]bool)
241 m[42] = true
242 if !m[42] {
243 t.Fatalf("42 is not present in the map")
244 }
245 if m[0] {
246 t.Fatalf("0 is present in the map")
247 }
248
249 n := testing.AllocsPerRun(1000, func() {
250 if m[0] {
251 t.Fatalf("0 is present in the map")
252 }
253 })
254 if n != 0 {
255 t.Fatalf("want 0 allocs, got %v", n)
256 }
257}
258
259func TestNonEscapingConvT2I(t *testing.T) {
260 m := make(map[I1]bool)
261 m[TM(42)] = true
262 if !m[TM(42)] {
263 t.Fatalf("42 is not present in the map")
264 }
265 if m[TM(0)] {
266 t.Fatalf("0 is present in the map")
267 }
268
269 n := testing.AllocsPerRun(1000, func() {
270 if m[TM(0)] {
271 t.Fatalf("0 is present in the map")
272 }
273 })
274 if n != 0 {
275 t.Fatalf("want 0 allocs, got %v", n)
276 }
277}
Dan Willemsenc78f7142017-07-26 13:08:14 -0700278
279func TestZeroConvT2x(t *testing.T) {
280 tests := []struct {
281 name string
282 fn func()
283 }{
284 {name: "E8", fn: func() { e = eight8 }}, // any byte-sized value does not allocate
285 {name: "E16", fn: func() { e = zero16 }}, // zero values do not allocate
286 {name: "E32", fn: func() { e = zero32 }},
287 {name: "E64", fn: func() { e = zero64 }},
288 {name: "Estr", fn: func() { e = zerostr }},
289 {name: "Eslice", fn: func() { e = zeroslice }},
290 {name: "Econstflt", fn: func() { e = 99.0 }}, // constants do not allocate
291 {name: "Econststr", fn: func() { e = "change" }},
292 {name: "I8", fn: func() { i1 = eight8I }},
293 {name: "I16", fn: func() { i1 = zero16I }},
294 {name: "I32", fn: func() { i1 = zero32I }},
295 {name: "I64", fn: func() { i1 = zero64I }},
296 {name: "Istr", fn: func() { i1 = zerostrI }},
297 {name: "Islice", fn: func() { i1 = zerosliceI }},
298 }
299
300 for _, test := range tests {
301 t.Run(test.name, func(t *testing.T) {
302 n := testing.AllocsPerRun(1000, test.fn)
303 if n != 0 {
304 t.Errorf("want zero allocs, got %v", n)
305 }
306 })
307 }
308}
309
310var (
311 eight8 uint8 = 8
312 eight8I T8 = 8
313
314 zero16 uint16 = 0
315 zero16I T16 = 0
316 one16 uint16 = 1
317
318 zero32 uint32 = 0
319 zero32I T32 = 0
320 one32 uint32 = 1
321
322 zero64 uint64 = 0
323 zero64I T64 = 0
324 one64 uint64 = 1
325
326 zerostr string = ""
327 zerostrI Tstr = ""
328 nzstr string = "abc"
329
330 zeroslice []byte = nil
331 zerosliceI Tslice = nil
332 nzslice []byte = []byte("abc")
333
334 zerobig [512]byte
335 nzbig [512]byte = [512]byte{511: 1}
336)
337
338func BenchmarkConvT2Ezero(b *testing.B) {
339 b.Run("zero", func(b *testing.B) {
340 b.Run("16", func(b *testing.B) {
341 for i := 0; i < b.N; i++ {
342 e = zero16
343 }
344 })
345 b.Run("32", func(b *testing.B) {
346 for i := 0; i < b.N; i++ {
347 e = zero32
348 }
349 })
350 b.Run("64", func(b *testing.B) {
351 for i := 0; i < b.N; i++ {
352 e = zero64
353 }
354 })
355 b.Run("str", func(b *testing.B) {
356 for i := 0; i < b.N; i++ {
357 e = zerostr
358 }
359 })
360 b.Run("slice", func(b *testing.B) {
361 for i := 0; i < b.N; i++ {
362 e = zeroslice
363 }
364 })
365 b.Run("big", func(b *testing.B) {
366 for i := 0; i < b.N; i++ {
367 e = zerobig
368 }
369 })
370 })
371 b.Run("nonzero", func(b *testing.B) {
372 b.Run("16", func(b *testing.B) {
373 for i := 0; i < b.N; i++ {
374 e = one16
375 }
376 })
377 b.Run("32", func(b *testing.B) {
378 for i := 0; i < b.N; i++ {
379 e = one32
380 }
381 })
382 b.Run("64", func(b *testing.B) {
383 for i := 0; i < b.N; i++ {
384 e = one64
385 }
386 })
387 b.Run("str", func(b *testing.B) {
388 for i := 0; i < b.N; i++ {
389 e = nzstr
390 }
391 })
392 b.Run("slice", func(b *testing.B) {
393 for i := 0; i < b.N; i++ {
394 e = nzslice
395 }
396 })
397 b.Run("big", func(b *testing.B) {
398 for i := 0; i < b.N; i++ {
399 e = nzbig
400 }
401 })
402 })
403}