Source file
src/runtime/iface_test.go
Documentation: runtime
1
2
3
4
5 package runtime_test
6
7 import (
8 "runtime"
9 "testing"
10 )
11
12 type I1 interface {
13 Method1()
14 }
15
16 type I2 interface {
17 Method1()
18 Method2()
19 }
20
21 type TS uint16
22 type TM uintptr
23 type TL [2]uintptr
24
25 func (TS) Method1() {}
26 func (TS) Method2() {}
27 func (TM) Method1() {}
28 func (TM) Method2() {}
29 func (TL) Method1() {}
30 func (TL) Method2() {}
31
32 type T8 uint8
33 type T16 uint16
34 type T32 uint32
35 type T64 uint64
36 type Tstr string
37 type Tslice []byte
38
39 func (T8) Method1() {}
40 func (T16) Method1() {}
41 func (T32) Method1() {}
42 func (T64) Method1() {}
43 func (Tstr) Method1() {}
44 func (Tslice) Method1() {}
45
46 var (
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
58 func 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
74 func BenchmarkEqEfaceConcrete(b *testing.B) {
75 for i := 0; i < b.N; i++ {
76 _ = e == ts
77 }
78 }
79
80 func BenchmarkEqIfaceConcrete(b *testing.B) {
81 for i := 0; i < b.N; i++ {
82 _ = i1 == ts
83 }
84 }
85
86 func BenchmarkNeEfaceConcrete(b *testing.B) {
87 for i := 0; i < b.N; i++ {
88 _ = e != ts
89 }
90 }
91
92 func BenchmarkNeIfaceConcrete(b *testing.B) {
93 for i := 0; i < b.N; i++ {
94 _ = i1 != ts
95 }
96 }
97
98 func 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
111 func BenchmarkConvT2ESmall(b *testing.B) {
112 for i := 0; i < b.N; i++ {
113 e = ts
114 }
115 }
116
117 func BenchmarkConvT2EUintptr(b *testing.B) {
118 for i := 0; i < b.N; i++ {
119 e = tm
120 }
121 }
122
123 func BenchmarkConvT2ELarge(b *testing.B) {
124 for i := 0; i < b.N; i++ {
125 e = tl
126 }
127 }
128
129 func BenchmarkConvT2ISmall(b *testing.B) {
130 for i := 0; i < b.N; i++ {
131 i1 = ts
132 }
133 }
134
135 func BenchmarkConvT2IUintptr(b *testing.B) {
136 for i := 0; i < b.N; i++ {
137 i1 = tm
138 }
139 }
140
141 func BenchmarkConvT2ILarge(b *testing.B) {
142 for i := 0; i < b.N; i++ {
143 i1 = tl
144 }
145 }
146
147 func BenchmarkConvI2E(b *testing.B) {
148 i2 = tm
149 for i := 0; i < b.N; i++ {
150 e = i2
151 }
152 }
153
154 func BenchmarkConvI2I(b *testing.B) {
155 i2 = tm
156 for i := 0; i < b.N; i++ {
157 i1 = i2
158 }
159 }
160
161 func BenchmarkAssertE2T(b *testing.B) {
162 e = tm
163 for i := 0; i < b.N; i++ {
164 tm = e.(TM)
165 }
166 }
167
168 func BenchmarkAssertE2TLarge(b *testing.B) {
169 e = tl
170 for i := 0; i < b.N; i++ {
171 tl = e.(TL)
172 }
173 }
174
175 func BenchmarkAssertE2I(b *testing.B) {
176 e = tm
177 for i := 0; i < b.N; i++ {
178 i1 = e.(I1)
179 }
180 }
181
182 func BenchmarkAssertI2T(b *testing.B) {
183 i1 = tm
184 for i := 0; i < b.N; i++ {
185 tm = i1.(TM)
186 }
187 }
188
189 func BenchmarkAssertI2I(b *testing.B) {
190 i1 = tm
191 for i := 0; i < b.N; i++ {
192 i2 = i1.(I2)
193 }
194 }
195
196 func BenchmarkAssertI2E(b *testing.B) {
197 i1 = tm
198 for i := 0; i < b.N; i++ {
199 e = i1.(any)
200 }
201 }
202
203 func BenchmarkAssertE2E(b *testing.B) {
204 e = tm
205 for i := 0; i < b.N; i++ {
206 e_ = e
207 }
208 }
209
210 func BenchmarkAssertE2T2(b *testing.B) {
211 e = tm
212 for i := 0; i < b.N; i++ {
213 tm, ok = e.(TM)
214 }
215 }
216
217 func BenchmarkAssertE2T2Blank(b *testing.B) {
218 e = tm
219 for i := 0; i < b.N; i++ {
220 _, ok = e.(TM)
221 }
222 }
223
224 func BenchmarkAssertI2E2(b *testing.B) {
225 i1 = tm
226 for i := 0; i < b.N; i++ {
227 e, ok = i1.(any)
228 }
229 }
230
231 func BenchmarkAssertI2E2Blank(b *testing.B) {
232 i1 = tm
233 for i := 0; i < b.N; i++ {
234 _, ok = i1.(any)
235 }
236 }
237
238 func BenchmarkAssertE2E2(b *testing.B) {
239 e = tm
240 for i := 0; i < b.N; i++ {
241 e_, ok = e.(any)
242 }
243 }
244
245 func BenchmarkAssertE2E2Blank(b *testing.B) {
246 e = tm
247 for i := 0; i < b.N; i++ {
248 _, ok = e.(any)
249 }
250 }
251
252 func 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
272 func 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
292 func TestZeroConvT2x(t *testing.T) {
293 tests := []struct {
294 name string
295 fn func()
296 }{
297 {name: "E8", fn: func() { e = eight8 }},
298 {name: "E16", fn: func() { e = zero16 }},
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 }},
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
323 var (
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
355 func 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
View as plain text