return slice{unsafe.Pointer(&zerobase), newLen, newLen}
}
- newcap := oldCap
- doublecap := newcap + newcap
- if newLen > doublecap {
- newcap = newLen
- } else {
- const threshold = 256
- if oldCap < threshold {
- newcap = doublecap
- } else {
- for {
- // Transition from growing 2x for small slices
- // to growing 1.25x for large slices. This formula
- // gives a smooth-ish transition between the two.
- newcap += (newcap + 3*threshold) >> 2
-
- // We need to check `newcap >= newLen` and whether `newcap` overflowed.
- // newLen is guaranteed to be larger than zero, hence
- // when newcap overflows then `uint(newcap) > uint(newLen)`.
- // This allows to check for both with the same comparison.
- if uint(newcap) >= uint(newLen) {
- break
- }
- }
-
- // Set newcap to the requested cap when
- // the newcap calculation overflowed.
- if newcap <= 0 {
- newcap = newLen
- }
- }
- }
+ newcap := nextslicecap(newLen, oldCap)
var overflow bool
var lenmem, newlenmem, capmem uintptr
return slice{p, newLen, newcap}
}
+// nextslicecap computes the next appropriate slice length.
+func nextslicecap(newLen, oldCap int) int {
+ newcap := oldCap
+ doublecap := newcap + newcap
+ if newLen > doublecap {
+ return newLen
+ }
+
+ const threshold = 256
+ if oldCap < threshold {
+ return doublecap
+ }
+ for {
+ // Transition from growing 2x for small slices
+ // to growing 1.25x for large slices. This formula
+ // gives a smooth-ish transition between the two.
+ newcap += (newcap + 3*threshold) >> 2
+
+ // We need to check `newcap >= newLen` and whether `newcap` overflowed.
+ // newLen is guaranteed to be larger than zero, hence
+ // when newcap overflows then `uint(newcap) > uint(newLen)`.
+ // This allows to check for both with the same comparison.
+ if uint(newcap) >= uint(newLen) {
+ break
+ }
+ }
+
+ // Set newcap to the requested cap when
+ // the newcap calculation overflowed.
+ if newcap <= 0 {
+ return newLen
+ }
+ return newcap
+}
+
//go:linkname reflect_growslice reflect.growslice
func reflect_growslice(et *_type, old slice, num int) slice {
// Semantically equivalent to slices.Grow, except that the caller