"unicode/utf8"
)
+// smallBufferSize is an initial allocation minimal capacity.
+const smallBufferSize = 64
+
// A Buffer is a variable-sized buffer of bytes with Read and Write methods.
// The zero value for Buffer is an empty buffer ready to use.
type Buffer struct {
- buf []byte // contents are the bytes buf[off : len(buf)]
- off int // read at &buf[off], write at &buf[len(buf)]
- bootstrap [64]byte // memory to hold first slice; helps small buffers avoid allocation.
- lastRead readOp // last read operation, so that Unread* can work correctly.
+ buf []byte // contents are the bytes buf[off : len(buf)]
+ off int // read at &buf[off], write at &buf[len(buf)]
+ lastRead readOp // last read operation, so that Unread* can work correctly.
// FIXME: it would be advisable to align Buffer to cachelines to avoid false
// sharing.
if i, ok := b.tryGrowByReslice(n); ok {
return i
}
- // Check if we can make use of bootstrap array.
- if b.buf == nil && n <= len(b.bootstrap) {
- b.buf = b.bootstrap[:n]
+ if b.buf == nil && n <= smallBufferSize {
+ b.buf = make([]byte, n, smallBufferSize)
return 0
}
c := cap(b.buf)
--- /dev/null
+// errorcheck -0 -m
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package foo
+
+import "bytes"
+
+// In order to get desired results, we need a combination of
+// both escape analysis and inlining.
+
+func bufferNotEscape() string {
+ // b itself does not escape, only its buf field will be
+ // copied during String() call, but object "handle" itself
+ // can be stack-allocated.
+ var b bytes.Buffer
+ b.WriteString("123") // ERROR "b does not escape"
+ b.Write([]byte{'4'}) // ERROR "b does not escape" "\[\]byte literal does not escape"
+ return b.String() // ERROR "b does not escape" "inlining call" "string\(bytes\.b\.buf\[bytes.b.off:\]\) escapes to heap"
+}
+
+func bufferNoEscape2(xs []string) int { // ERROR "xs does not escape"
+ b := bytes.NewBuffer(make([]byte, 0, 64)) // ERROR "inlining call" "make\(\[\]byte, 0, 64\) does not escape" "&bytes.Buffer literal does not escape"
+ for _, x := range xs {
+ b.WriteString(x)
+ }
+ return b.Len() // ERROR "inlining call"
+}
+
+func bufferNoEscape3(xs []string) string { // ERROR "xs does not escape"
+ b := bytes.NewBuffer(make([]byte, 0, 64)) // ERROR "inlining call" "make\(\[\]byte, 0, 64\) does not escape" "&bytes.Buffer literal does not escape"
+ for _, x := range xs {
+ b.WriteString(x)
+ b.WriteByte(',')
+ }
+ return b.String() // ERROR "inlining call" "string\(bytes.b.buf\[bytes\.b\.off:\]\) escapes to heap"
+}