Source file
src/runtime/slice_test.go
1
2
3
4
5 package runtime_test
6
7 import (
8 "fmt"
9 "internal/asan"
10 "internal/goexperiment"
11 "internal/msan"
12 "internal/race"
13 "internal/testenv"
14 "runtime"
15 "testing"
16 )
17
18 const N = 20
19
20 func BenchmarkMakeSliceCopy(b *testing.B) {
21 const length = 32
22 var bytes = make([]byte, 8*length)
23 var ints = make([]int, length)
24 var ptrs = make([]*byte, length)
25 b.Run("mallocmove", func(b *testing.B) {
26 b.Run("Byte", func(b *testing.B) {
27 var x []byte
28 for i := 0; i < b.N; i++ {
29 x = make([]byte, len(bytes))
30 copy(x, bytes)
31 }
32 })
33 b.Run("Int", func(b *testing.B) {
34 var x []int
35 for i := 0; i < b.N; i++ {
36 x = make([]int, len(ints))
37 copy(x, ints)
38 }
39 })
40 b.Run("Ptr", func(b *testing.B) {
41 var x []*byte
42 for i := 0; i < b.N; i++ {
43 x = make([]*byte, len(ptrs))
44 copy(x, ptrs)
45 }
46
47 })
48 })
49 b.Run("makecopy", func(b *testing.B) {
50 b.Run("Byte", func(b *testing.B) {
51 var x []byte
52 for i := 0; i < b.N; i++ {
53 x = make([]byte, 8*length)
54 copy(x, bytes)
55 }
56 })
57 b.Run("Int", func(b *testing.B) {
58 var x []int
59 for i := 0; i < b.N; i++ {
60 x = make([]int, length)
61 copy(x, ints)
62 }
63 })
64 b.Run("Ptr", func(b *testing.B) {
65 var x []*byte
66 for i := 0; i < b.N; i++ {
67 x = make([]*byte, length)
68 copy(x, ptrs)
69 }
70
71 })
72 })
73 b.Run("nilappend", func(b *testing.B) {
74 b.Run("Byte", func(b *testing.B) {
75 var x []byte
76 for i := 0; i < b.N; i++ {
77 x = append([]byte(nil), bytes...)
78 _ = x
79 }
80 })
81 b.Run("Int", func(b *testing.B) {
82 var x []int
83 for i := 0; i < b.N; i++ {
84 x = append([]int(nil), ints...)
85 _ = x
86 }
87 })
88 b.Run("Ptr", func(b *testing.B) {
89 var x []*byte
90 for i := 0; i < b.N; i++ {
91 x = append([]*byte(nil), ptrs...)
92 _ = x
93 }
94 })
95 })
96 }
97
98 type sliceHolder[T any] struct {
99 data [1][]T
100 }
101
102
103 func benchmarkComplexSrc[T any](b *testing.B, typeName string, size int) {
104 var src = &sliceHolder[T]{}
105 (*src).data[0] = make([]T, size)
106
107 b.Run(typeName, func(b *testing.B) {
108 b.Run("mallocmove", func(b *testing.B) {
109 var dst []T
110 for i := 0; i < b.N; i++ {
111 dst = make([]T, len((*src).data[0]))
112 copy(dst, (*src).data[0])
113 }
114 })
115 b.Run("makecopy", func(b *testing.B) {
116 var dst []T
117 for i := 0; i < b.N; i++ {
118 dst = make([]T, size)
119 copy(dst, (*src).data[0])
120 }
121 })
122 b.Run("nilappend", func(b *testing.B) {
123 var dst []T
124 for i := 0; i < b.N; i++ {
125 dst = append([]T(nil), (*src).data[0]...)
126 _ = dst
127 }
128 })
129 })
130 }
131
132
133 func benchmarkComplexDst[T any](b *testing.B, typeName string, size int) {
134 var src = make([]T, size)
135
136 b.Run(typeName, func(b *testing.B) {
137 b.Run("mallocmove", func(b *testing.B) {
138 var dst = &sliceHolder[T]{}
139 for i := 0; i < b.N; i++ {
140 (*dst).data[0] = make([]T, len(src))
141 copy((*dst).data[0], src)
142 }
143 })
144 b.Run("makecopy", func(b *testing.B) {
145 var dst = &sliceHolder[T]{}
146 for i := 0; i < b.N; i++ {
147 (*dst).data[0] = make([]T, size)
148 copy((*dst).data[0], src)
149 }
150 })
151 b.Run("nilappend", func(b *testing.B) {
152 var dst = &sliceHolder[T]{}
153 for i := 0; i < b.N; i++ {
154 (*dst).data[0] = append([]T(nil), src...)
155 _ = (*dst).data[0]
156 }
157 })
158 })
159 }
160
161 func BenchmarkMakeSliceCopyComplexExpressions(b *testing.B) {
162 const length = 32
163
164 b.Run("Src", func(b *testing.B) {
165 benchmarkComplexSrc[byte](b, "Byte", 8*length)
166 benchmarkComplexSrc[int](b, "Int", length)
167 benchmarkComplexSrc[*byte](b, "Ptr", length)
168 })
169
170 b.Run("Dst", func(b *testing.B) {
171 benchmarkComplexDst[byte](b, "Byte", 8*length)
172 benchmarkComplexDst[int](b, "Int", length)
173 benchmarkComplexDst[*byte](b, "Ptr", length)
174 })
175 }
176
177 type (
178 struct24 struct{ a, b, c int64 }
179 struct32 struct{ a, b, c, d int64 }
180 struct40 struct{ a, b, c, d, e int64 }
181 )
182
183 func BenchmarkMakeSlice(b *testing.B) {
184 const length = 2
185 b.Run("Byte", func(b *testing.B) {
186 var x []byte
187 for i := 0; i < b.N; i++ {
188 x = make([]byte, length, 2*length)
189 _ = x
190 }
191 })
192 b.Run("Int16", func(b *testing.B) {
193 var x []int16
194 for i := 0; i < b.N; i++ {
195 x = make([]int16, length, 2*length)
196 _ = x
197 }
198 })
199 b.Run("Int", func(b *testing.B) {
200 var x []int
201 for i := 0; i < b.N; i++ {
202 x = make([]int, length, 2*length)
203 _ = x
204 }
205 })
206 b.Run("Ptr", func(b *testing.B) {
207 var x []*byte
208 for i := 0; i < b.N; i++ {
209 x = make([]*byte, length, 2*length)
210 _ = x
211 }
212 })
213 b.Run("Struct", func(b *testing.B) {
214 b.Run("24", func(b *testing.B) {
215 var x []struct24
216 for i := 0; i < b.N; i++ {
217 x = make([]struct24, length, 2*length)
218 _ = x
219 }
220 })
221 b.Run("32", func(b *testing.B) {
222 var x []struct32
223 for i := 0; i < b.N; i++ {
224 x = make([]struct32, length, 2*length)
225 _ = x
226 }
227 })
228 b.Run("40", func(b *testing.B) {
229 var x []struct40
230 for i := 0; i < b.N; i++ {
231 x = make([]struct40, length, 2*length)
232 _ = x
233 }
234 })
235
236 })
237 }
238
239 func BenchmarkGrowSlice(b *testing.B) {
240 b.Run("Byte", func(b *testing.B) {
241 x := make([]byte, 9)
242 for i := 0; i < b.N; i++ {
243 _ = append([]byte(nil), x...)
244 }
245 })
246 b.Run("Int16", func(b *testing.B) {
247 x := make([]int16, 9)
248 for i := 0; i < b.N; i++ {
249 _ = append([]int16(nil), x...)
250 }
251 })
252 b.Run("Int", func(b *testing.B) {
253 x := make([]int, 9)
254 for i := 0; i < b.N; i++ {
255 _ = append([]int(nil), x...)
256 }
257 })
258 b.Run("Ptr", func(b *testing.B) {
259 x := make([]*byte, 9)
260 for i := 0; i < b.N; i++ {
261 _ = append([]*byte(nil), x...)
262 }
263 })
264 b.Run("Struct", func(b *testing.B) {
265 b.Run("24", func(b *testing.B) {
266 x := make([]struct24, 9)
267 for i := 0; i < b.N; i++ {
268 _ = append([]struct24(nil), x...)
269 }
270 })
271 b.Run("32", func(b *testing.B) {
272 x := make([]struct32, 9)
273 for i := 0; i < b.N; i++ {
274 _ = append([]struct32(nil), x...)
275 }
276 })
277 b.Run("40", func(b *testing.B) {
278 x := make([]struct40, 9)
279 for i := 0; i < b.N; i++ {
280 _ = append([]struct40(nil), x...)
281 }
282 })
283
284 })
285 }
286
287 var (
288 SinkIntSlice []int
289 SinkIntPointerSlice []*int
290 )
291
292 func BenchmarkExtendSlice(b *testing.B) {
293 var length = 4
294 b.Run("IntSlice", func(b *testing.B) {
295 s := make([]int, 0, length)
296 for i := 0; i < b.N; i++ {
297 s = append(s[:0:length/2], make([]int, length)...)
298 }
299 SinkIntSlice = s
300 })
301 b.Run("PointerSlice", func(b *testing.B) {
302 s := make([]*int, 0, length)
303 for i := 0; i < b.N; i++ {
304 s = append(s[:0:length/2], make([]*int, length)...)
305 }
306 SinkIntPointerSlice = s
307 })
308 b.Run("NoGrow", func(b *testing.B) {
309 s := make([]int, 0, length)
310 for i := 0; i < b.N; i++ {
311 s = append(s[:0:length], make([]int, length)...)
312 }
313 SinkIntSlice = s
314 })
315 }
316
317 func BenchmarkAppend(b *testing.B) {
318 b.StopTimer()
319 x := make([]int, 0, N)
320 b.StartTimer()
321 for i := 0; i < b.N; i++ {
322 x = x[0:0]
323 for j := 0; j < N; j++ {
324 x = append(x, j)
325 }
326 }
327 }
328
329 func BenchmarkAppendGrowByte(b *testing.B) {
330 for i := 0; i < b.N; i++ {
331 var x []byte
332 for j := 0; j < 1<<20; j++ {
333 x = append(x, byte(j))
334 }
335 }
336 }
337
338 func BenchmarkAppendGrowString(b *testing.B) {
339 var s string
340 for i := 0; i < b.N; i++ {
341 var x []string
342 for j := 0; j < 1<<20; j++ {
343 x = append(x, s)
344 }
345 }
346 }
347
348 func BenchmarkAppendSlice(b *testing.B) {
349 for _, length := range []int{1, 4, 7, 8, 15, 16, 32} {
350 b.Run(fmt.Sprint(length, "Bytes"), func(b *testing.B) {
351 x := make([]byte, 0, N)
352 y := make([]byte, length)
353 for i := 0; i < b.N; i++ {
354 x = x[0:0]
355 x = append(x, y...)
356 }
357 })
358 }
359 }
360
361 var (
362 blackhole []byte
363 )
364
365 func BenchmarkAppendSliceLarge(b *testing.B) {
366 for _, length := range []int{1 << 10, 4 << 10, 16 << 10, 64 << 10, 256 << 10, 1024 << 10} {
367 y := make([]byte, length)
368 b.Run(fmt.Sprint(length, "Bytes"), func(b *testing.B) {
369 for i := 0; i < b.N; i++ {
370 blackhole = nil
371 blackhole = append(blackhole, y...)
372 }
373 })
374 }
375 }
376
377 func BenchmarkAppendStr(b *testing.B) {
378 for _, str := range []string{
379 "1",
380 "1234",
381 "12345678",
382 "1234567890123456",
383 "12345678901234567890123456789012",
384 } {
385 b.Run(fmt.Sprint(len(str), "Bytes"), func(b *testing.B) {
386 x := make([]byte, 0, N)
387 for i := 0; i < b.N; i++ {
388 x = x[0:0]
389 x = append(x, str...)
390 }
391 })
392 }
393 }
394
395 func BenchmarkAppendSpecialCase(b *testing.B) {
396 b.StopTimer()
397 x := make([]int, 0, N)
398 b.StartTimer()
399 for i := 0; i < b.N; i++ {
400 x = x[0:0]
401 for j := 0; j < N; j++ {
402 if len(x) < cap(x) {
403 x = x[:len(x)+1]
404 x[len(x)-1] = j
405 } else {
406 x = append(x, j)
407 }
408 }
409 }
410 }
411
412 var x []int
413
414 func f() int {
415 x[:1][0] = 3
416 return 2
417 }
418
419 func TestSideEffectOrder(t *testing.T) {
420 x = make([]int, 0, 10)
421 x = append(x, 1, f())
422 if x[0] != 1 || x[1] != 2 {
423 t.Error("append failed: ", x[0], x[1])
424 }
425 }
426
427 func TestAppendOverlap(t *testing.T) {
428 x := []byte("1234")
429 x = append(x[1:], x...)
430 got := string(x)
431 want := "2341234"
432 if got != want {
433 t.Errorf("overlap failed: got %q want %q", got, want)
434 }
435 }
436
437 func BenchmarkCopy(b *testing.B) {
438 for _, l := range []int{1, 2, 4, 8, 12, 16, 32, 128, 1024} {
439 buf := make([]byte, 4096)
440 b.Run(fmt.Sprint(l, "Byte"), func(b *testing.B) {
441 s := make([]byte, l)
442 var n int
443 for i := 0; i < b.N; i++ {
444 n = copy(buf, s)
445 }
446 b.SetBytes(int64(n))
447 })
448 b.Run(fmt.Sprint(l, "String"), func(b *testing.B) {
449 s := string(make([]byte, l))
450 var n int
451 for i := 0; i < b.N; i++ {
452 n = copy(buf, s)
453 }
454 b.SetBytes(int64(n))
455 })
456 }
457 }
458
459 var (
460 sByte []byte
461 s1Ptr []uintptr
462 s2Ptr [][2]uintptr
463 s3Ptr [][3]uintptr
464 s4Ptr [][4]uintptr
465 )
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481 func BenchmarkAppendInPlace(b *testing.B) {
482 b.Run("NoGrow", func(b *testing.B) {
483 const C = 128
484
485 b.Run("Byte", func(b *testing.B) {
486 for i := 0; i < b.N; i++ {
487 sByte = make([]byte, C)
488 for j := 0; j < C; j++ {
489 sByte = append(sByte, 0x77)
490 }
491 }
492 })
493
494 b.Run("1Ptr", func(b *testing.B) {
495 for i := 0; i < b.N; i++ {
496 s1Ptr = make([]uintptr, C)
497 for j := 0; j < C; j++ {
498 s1Ptr = append(s1Ptr, 0x77)
499 }
500 }
501 })
502
503 b.Run("2Ptr", func(b *testing.B) {
504 for i := 0; i < b.N; i++ {
505 s2Ptr = make([][2]uintptr, C)
506 for j := 0; j < C; j++ {
507 s2Ptr = append(s2Ptr, [2]uintptr{0x77, 0x88})
508 }
509 }
510 })
511
512 b.Run("3Ptr", func(b *testing.B) {
513 for i := 0; i < b.N; i++ {
514 s3Ptr = make([][3]uintptr, C)
515 for j := 0; j < C; j++ {
516 s3Ptr = append(s3Ptr, [3]uintptr{0x77, 0x88, 0x99})
517 }
518 }
519 })
520
521 b.Run("4Ptr", func(b *testing.B) {
522 for i := 0; i < b.N; i++ {
523 s4Ptr = make([][4]uintptr, C)
524 for j := 0; j < C; j++ {
525 s4Ptr = append(s4Ptr, [4]uintptr{0x77, 0x88, 0x99, 0xAA})
526 }
527 }
528 })
529
530 })
531
532 b.Run("Grow", func(b *testing.B) {
533 const C = 5
534
535 b.Run("Byte", func(b *testing.B) {
536 for i := 0; i < b.N; i++ {
537 sByte = make([]byte, 0)
538 for j := 0; j < C; j++ {
539 sByte = append(sByte, 0x77)
540 sByte = sByte[:cap(sByte)]
541 }
542 }
543 })
544
545 b.Run("1Ptr", func(b *testing.B) {
546 for i := 0; i < b.N; i++ {
547 s1Ptr = make([]uintptr, 0)
548 for j := 0; j < C; j++ {
549 s1Ptr = append(s1Ptr, 0x77)
550 s1Ptr = s1Ptr[:cap(s1Ptr)]
551 }
552 }
553 })
554
555 b.Run("2Ptr", func(b *testing.B) {
556 for i := 0; i < b.N; i++ {
557 s2Ptr = make([][2]uintptr, 0)
558 for j := 0; j < C; j++ {
559 s2Ptr = append(s2Ptr, [2]uintptr{0x77, 0x88})
560 s2Ptr = s2Ptr[:cap(s2Ptr)]
561 }
562 }
563 })
564
565 b.Run("3Ptr", func(b *testing.B) {
566 for i := 0; i < b.N; i++ {
567 s3Ptr = make([][3]uintptr, 0)
568 for j := 0; j < C; j++ {
569 s3Ptr = append(s3Ptr, [3]uintptr{0x77, 0x88, 0x99})
570 s3Ptr = s3Ptr[:cap(s3Ptr)]
571 }
572 }
573 })
574
575 b.Run("4Ptr", func(b *testing.B) {
576 for i := 0; i < b.N; i++ {
577 s4Ptr = make([][4]uintptr, 0)
578 for j := 0; j < C; j++ {
579 s4Ptr = append(s4Ptr, [4]uintptr{0x77, 0x88, 0x99, 0xAA})
580 s4Ptr = s4Ptr[:cap(s4Ptr)]
581 }
582 }
583 })
584
585 })
586 }
587
588
589 func byteSlice(n int) []byte {
590 var r []byte
591 for i := range n {
592 r = append(r, byte(i))
593 }
594 return r
595 }
596 func TestAppendByteInLoop(t *testing.T) {
597 testenv.SkipIfOptimizationOff(t)
598 if race.Enabled {
599 t.Skip("skipping in -race mode")
600 }
601 if asan.Enabled || msan.Enabled {
602 t.Skip("skipping in sanitizer mode")
603 }
604 for _, test := range [][3]int{
605 {0, 0, 0},
606 {1, 1, 8},
607 {2, 1, 8},
608 {8, 1, 8},
609 {9, 1, 16},
610 {16, 1, 16},
611 {17, 1, 24},
612 {24, 1, 24},
613 {25, 1, 32},
614 {32, 1, 32},
615 {33, 1, 64},
616 {48, 1, 64},
617 {49, 1, 64},
618 {64, 1, 64},
619 {65, 2, 128},
620 } {
621 n := test[0]
622 want := test[1]
623 wantCap := test[2]
624
625 if goexperiment.RuntimeFreegc && n > 64 {
626
627
628
629
630
631
632
633 want = 1
634 }
635
636 var r []byte
637 got := testing.AllocsPerRun(10, func() {
638 r = byteSlice(n)
639 })
640 if got != float64(want) {
641 t.Errorf("for size %d, got %f allocs want %d", n, got, want)
642 }
643 if cap(r) != wantCap {
644 t.Errorf("for size %d, got capacity %d want %d", n, cap(r), wantCap)
645 }
646 }
647 }
648
649
650 func ptrSlice(n int, p *[]*byte) {
651 var r []*byte
652 for range n {
653 r = append(r, nil)
654 }
655 *p = r
656 }
657 func TestAppendPtrInLoop(t *testing.T) {
658 testenv.SkipIfOptimizationOff(t)
659 if race.Enabled {
660 t.Skip("skipping in -race mode")
661 }
662 if asan.Enabled || msan.Enabled {
663 t.Skip("skipping in sanitizer mode")
664 }
665 var tests [][3]int
666 if runtime.PtrSize == 8 {
667 tests = [][3]int{
668 {0, 0, 0},
669 {1, 1, 1},
670 {2, 1, 2},
671 {3, 1, 3},
672 {4, 1, 4},
673 {5, 1, 8},
674 {6, 1, 8},
675 {7, 1, 8},
676 {8, 1, 8},
677 {9, 2, 16},
678 }
679 } else {
680 tests = [][3]int{
681 {0, 0, 0},
682 {1, 1, 2},
683 {2, 1, 2},
684 {3, 1, 4},
685 {4, 1, 4},
686 {5, 1, 6},
687 {6, 1, 6},
688 {7, 1, 8},
689 {8, 1, 8},
690 {9, 1, 16},
691 {10, 1, 16},
692 {11, 1, 16},
693 {12, 1, 16},
694 {13, 1, 16},
695 {14, 1, 16},
696 {15, 1, 16},
697 {16, 1, 16},
698 {17, 2, 32},
699 }
700 }
701 for _, test := range tests {
702 n := test[0]
703 want := test[1]
704 wantCap := test[2]
705 var r []*byte
706 got := testing.AllocsPerRun(10, func() {
707 ptrSlice(n, &r)
708 })
709 if got != float64(want) {
710 t.Errorf("for size %d, got %f allocs want %d", n, got, want)
711 }
712 if cap(r) != wantCap {
713 t.Errorf("for size %d, got capacity %d want %d", n, cap(r), wantCap)
714 }
715 }
716 }
717
718
719 func byteCapSlice(n int) ([]byte, int) {
720 var r []byte
721 for i := range n {
722 r = append(r, byte(i))
723 }
724 return r, cap(r)
725 }
726 func TestAppendByteCapInLoop(t *testing.T) {
727 testenv.SkipIfOptimizationOff(t)
728 if race.Enabled {
729 t.Skip("skipping in -race mode")
730 }
731 if asan.Enabled || msan.Enabled {
732 t.Skip("skipping in sanitizer mode")
733 }
734 for _, test := range [][3]int{
735 {0, 0, 0},
736 {1, 1, 8},
737 {2, 1, 8},
738 {8, 1, 8},
739 {9, 1, 16},
740 {16, 1, 16},
741 {17, 1, 24},
742 {24, 1, 24},
743 {25, 1, 32},
744 {32, 1, 32},
745 {33, 1, 64},
746 {48, 1, 64},
747 {49, 1, 64},
748 {64, 1, 64},
749 {65, 2, 128},
750 } {
751 n := test[0]
752 want := test[1]
753 wantCap := test[2]
754
755 if goexperiment.RuntimeFreegc && n > 64 {
756
757 want = 1
758 }
759
760 var r []byte
761 got := testing.AllocsPerRun(10, func() {
762 r, _ = byteCapSlice(n)
763 })
764 if got != float64(want) {
765 t.Errorf("for size %d, got %f allocs want %d", n, got, want)
766 }
767 if cap(r) != wantCap {
768 t.Errorf("for size %d, got capacity %d want %d", n, cap(r), wantCap)
769 }
770 }
771 }
772
773 func TestAppendGeneric(t *testing.T) {
774 type I *int
775 r := testAppendGeneric[I](100)
776 if len(r) != 100 {
777 t.Errorf("bad length")
778 }
779 }
780
781
782 func testAppendGeneric[E any](n int) []E {
783 var r []E
784 var z E
785 for range n {
786 r = append(r, z)
787 }
788 return r
789 }
790
791 func appendSomeBytes(r []byte, s []byte) []byte {
792 for _, b := range s {
793 r = append(r, b)
794 }
795 return r
796 }
797
798 func TestAppendOfArg(t *testing.T) {
799 r := make([]byte, 24)
800 for i := 0; i < 24; i++ {
801 r[i] = byte(i)
802 }
803 appendSomeBytes(r, []byte{25, 26, 27})
804
805
806 s := make([]byte, 24)
807 for i := 0; i < 24; i++ {
808 s[i] = 99
809 }
810 appendSomeBytes(s, []byte{99, 99, 99})
811
812 for i, b := range r {
813 if b != byte(i) {
814 t.Errorf("r[%d]=%d, want %d", i, b, byte(i))
815 }
816 }
817
818 }
819
820 func BenchmarkAppendInLoop(b *testing.B) {
821 for _, size := range []int{0, 1, 8, 16, 32, 64, 128} {
822 b.Run(fmt.Sprintf("%d", size),
823 func(b *testing.B) {
824 b.ReportAllocs()
825 for b.Loop() {
826 byteSlice(size)
827 }
828 })
829 }
830 }
831
832 func TestMoveToHeapEarly(t *testing.T) {
833
834 var x []int
835 y := x
836 for range 5 {
837 x = append(x, 5)
838 }
839 _ = y
840 }
841
842 func TestMoveToHeapCap(t *testing.T) {
843 var c int
844 r := func() []byte {
845 var s []byte
846 for i := range 10 {
847 s = append(s, byte(i))
848 }
849 c = cap(s)
850 return s
851 }()
852 if c != cap(r) {
853 t.Errorf("got cap=%d, want %d", c, cap(r))
854 }
855 sinkSlice = r
856 }
857
858
859 func runit(f func()) {
860 f()
861 }
862
863 func TestMoveToHeapClosure1(t *testing.T) {
864 var c int
865 r := func() []byte {
866 var s []byte
867 for i := range 10 {
868 s = append(s, byte(i))
869 }
870 runit(func() {
871 c = cap(s)
872 })
873 return s
874 }()
875 if c != cap(r) {
876 t.Errorf("got cap=%d, want %d", c, cap(r))
877 }
878 sinkSlice = r
879 }
880 func TestMoveToHeapClosure2(t *testing.T) {
881 var c int
882 r := func() []byte {
883 var s []byte
884 for i := range 10 {
885 s = append(s, byte(i))
886 }
887 c = func() int {
888 return cap(s)
889 }()
890 return s
891 }()
892 if c != cap(r) {
893 t.Errorf("got cap=%d, want %d", c, cap(r))
894 }
895 sinkSlice = r
896 }
897
898
899 func buildClosure(t *testing.T) ([]byte, func()) {
900 var s []byte
901 for i := range 20 {
902 s = append(s, byte(i))
903 }
904 c := func() {
905 for i, b := range s {
906 if b != byte(i) {
907 t.Errorf("s[%d]=%d, want %d", i, b, i)
908 }
909 }
910 }
911 return s, c
912 }
913
914 func TestMoveToHeapClosure3(t *testing.T) {
915 _, f := buildClosure(t)
916 overwriteStack(0)
917 f()
918 }
919
920
921 func overwriteStack(n int) uint64 {
922 var x [100]uint64
923 for i := range x {
924 x[i] = 0xabcdabcdabcdabcd
925 }
926 return x[n]
927 }
928
929 var sinkSlice []byte
930
View as plain text