aboutsummaryrefslogtreecommitdiff
path: root/src/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime')
-rw-r--r--src/runtime/runtime_test.go40
-rw-r--r--src/runtime/slice.go14
2 files changed, 52 insertions, 2 deletions
diff --git a/src/runtime/runtime_test.go b/src/runtime/runtime_test.go
index f65562ab91..75fc9bcb84 100644
--- a/src/runtime/runtime_test.go
+++ b/src/runtime/runtime_test.go
@@ -261,3 +261,43 @@ func TestBadOpen(t *testing.T) {
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
+ }
+ }
+}
diff --git a/src/runtime/slice.go b/src/runtime/slice.go
index 15820a5181..5cda11d9b0 100644
--- a/src/runtime/slice.go
+++ b/src/runtime/slice.go
@@ -33,12 +33,22 @@ func makeslice(t *slicetype, len64, cap64 int64) slice {
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"))
}