"func @\"\".selectgo (@\"\".sel·1 *byte)\n" +
"func @\"\".block ()\n" +
"func @\"\".makeslice (@\"\".typ·2 *byte, @\"\".nel·3 int64, @\"\".cap·4 int64) (@\"\".ary·1 []any)\n" +
- "func @\"\".growslice (@\"\".typ·2 *byte, @\"\".old·3 []any, @\"\".n·4 int) (@\"\".ary·1 []any)\n" +
+ "func @\"\".growslice (@\"\".typ·2 *byte, @\"\".old·3 []any, @\"\".cap·4 int) (@\"\".ary·1 []any)\n" +
+ "func @\"\".growslice_n (@\"\".typ·2 *byte, @\"\".old·3 []any, @\"\".n·4 int) (@\"\".ary·1 []any)\n" +
"func @\"\".memmove (@\"\".to·1 *any, @\"\".frm·2 *any, @\"\".length·3 uintptr)\n" +
"func @\"\".memclr (@\"\".ptr·1 *byte, @\"\".length·2 uintptr)\n" +
"func @\"\".memequal (@\"\".x·2 *any, @\"\".y·3 *any, @\"\".size·4 uintptr) (? bool)\n" +
func block()
func makeslice(typ *byte, nel int64, cap int64) (ary []any)
-func growslice(typ *byte, old []any, n int) (ary []any)
+func growslice(typ *byte, old []any, cap int) (ary []any)
+func growslice_n(typ *byte, old []any, n int) (ary []any)
func memmove(to *any, frm *any, length uintptr)
func memclr(ptr *byte, length uintptr)
// init {
// s := l1
// if n := len(l1) + len(l2) - cap(s); n > 0 {
-// s = growslice(s, n)
+// s = growslice_n(s, n)
// }
// s = s[:len(l1)+len(l2)]
// memmove(&s[len(l1)], &l2[0], len(l2)*sizeof(T))
nif.Left = Nod(OGT, nt, Nodintconst(0))
- // instantiate growslice(Type*, []any, int) []any
- fn := syslook("growslice", 1) // growslice(<type>, old []T, n int64) (ret []T)
+ // instantiate growslice_n(Type*, []any, int) []any
+ fn := syslook("growslice_n", 1) // growslice_n(<type>, old []T, n int64) (ret []T)
substArgTypes(fn, s.Type.Type, s.Type.Type)
- // s = growslice(T, s, n)
+ // s = growslice_n(T, s, n)
nif.Nbody = list1(Nod(OAS, s, mkcall1(fn, s.Type, &nif.Ninit, typename(s.Type), s, nt)))
l = list(l, nif)
// s := src
// const argc = len(args) - 1
// if cap(s) - len(s) < argc {
-// s = growslice(s, argc)
+// s = growslice(s, len(s)+argc)
// }
// n := len(s)
// s = s[:n+argc]
nx := Nod(OIF, nil, nil) // if cap(s) - len(s) < argc
nx.Left = Nod(OLT, Nod(OSUB, Nod(OCAP, ns, nil), Nod(OLEN, ns, nil)), na)
- fn := syslook("growslice", 1) // growslice(<type>, old []T, n int) (ret []T)
+ fn := syslook("growslice", 1) // growslice(<type>, old []T, mincap int) (ret []T)
substArgTypes(fn, ns.Type.Type, ns.Type.Type)
- nx.Nbody = list1(Nod(OAS, ns, mkcall1(fn, ns.Type, &nx.Ninit, typename(ns.Type), ns, na)))
+ nx.Nbody = list1(Nod(OAS, ns, mkcall1(fn, ns.Type, &nx.Ninit, typename(ns.Type), ns, Nod(OADD, Nod(OLEN, ns, nil), na))))
l = list(l, nx)
t.Errorf("close()=%d, want -1", c)
}
}
+
+func TestAppendGrowth(t *testing.T) {
+ var x []int64
+ check := func(want int) {
+ if cap(x) != want {
+ t.Errorf("len=%d, cap=%d, want cap=%d", len(x), cap(x), want)
+ }
+ }
+
+ check(0)
+ want := 1
+ for i := 1; i <= 100; i++ {
+ x = append(x, 1)
+ check(want)
+ if i&(i-1) == 0 {
+ want = 2 * i
+ }
+ }
+}
+
+var One = []int64{1}
+
+func TestAppendSliceGrowth(t *testing.T) {
+ var x []int64
+ check := func(want int) {
+ if cap(x) != want {
+ t.Errorf("len=%d, cap=%d, want cap=%d", len(x), cap(x), want)
+ }
+ }
+
+ check(0)
+ want := 1
+ for i := 1; i <= 100; i++ {
+ x = append(x, One...)
+ check(want)
+ if i&(i-1) == 0 {
+ want = 2 * i
+ }
+ }
+}
return slice{p, len, cap}
}
-func growslice(t *slicetype, old slice, n int) slice {
+// growslice_n is a variant of growslice that takes the number of new elements
+// instead of the new minimum capacity.
+// TODO(rsc): This is used by append(slice, slice...).
+// The compiler should change that code to use growslice directly (issue #11419).
+func growslice_n(t *slicetype, old slice, n int) slice {
if n < 1 {
panic(errorString("growslice: invalid n"))
}
+ return growslice(t, old, old.cap+n)
+}
- cap := old.cap + n
+// growslice handles slice growth during append.
+// It is passed the slice type, the old slice, and the desired new minimum capacity,
+// and it returns a new slice with at least that capacity, with the old data
+// copied into it.
+func growslice(t *slicetype, old slice, cap int) slice {
if cap < old.cap || t.elem.size > 0 && uintptr(cap) > _MaxMem/uintptr(t.elem.size) {
panic(errorString("growslice: cap out of range"))
}