aboutsummaryrefslogtreecommitdiff
path: root/src/internal/pkgbits/decoder.go
diff options
context:
space:
mode:
authorDavid Chase <drchase@google.com>2022-09-27 14:37:35 -0400
committerDavid Chase <drchase@google.com>2022-09-27 20:58:46 +0000
commitcaa8e1f97788d4276276d68610fadc6179a022ee (patch)
tree03ac749b283a8498169819642eb1c9e6891f2302 /src/internal/pkgbits/decoder.go
parente8afb2911125ad65ddc02f7b83ab78a3e2f573b7 (diff)
downloadgo-caa8e1f97788d4276276d68610fadc6179a022ee.tar.xz
cmd/compile: make a type-specialized copy of encoding/binary.ReadUvarint
This is to get better escape analysis for a frequently-allocated object. Change-Id: I1942a4e1c3cd1f0fa870bc8433a0165c18ce9c75 Reviewed-on: https://go-review.googlesource.com/c/go/+/435336 Reviewed-by: Keith Randall <khr@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Keith Randall <khr@google.com> Run-TryBot: David Chase <drchase@google.com> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Diffstat (limited to 'src/internal/pkgbits/decoder.go')
-rw-r--r--src/internal/pkgbits/decoder.go31
1 files changed, 30 insertions, 1 deletions
diff --git a/src/internal/pkgbits/decoder.go b/src/internal/pkgbits/decoder.go
index 1a18da3301..4fe024d4f1 100644
--- a/src/internal/pkgbits/decoder.go
+++ b/src/internal/pkgbits/decoder.go
@@ -6,6 +6,7 @@ package pkgbits
import (
"encoding/binary"
+ "errors"
"fmt"
"go/constant"
"go/token"
@@ -246,11 +247,39 @@ func (r *Decoder) checkErr(err error) {
}
func (r *Decoder) rawUvarint() uint64 {
- x, err := binary.ReadUvarint(&r.Data)
+ x, err := readUvarint(&r.Data)
r.checkErr(err)
return x
}
+// readUvarint is a type-specialized copy of encoding/binary.ReadUvarint.
+// This avoids the interface conversion and thus has better escape properties,
+// which flows up the stack.
+func readUvarint(r *strings.Reader) (uint64, error) {
+ var x uint64
+ var s uint
+ for i := 0; i < binary.MaxVarintLen64; i++ {
+ b, err := r.ReadByte()
+ if err != nil {
+ if i > 0 && err == io.EOF {
+ err = io.ErrUnexpectedEOF
+ }
+ return x, err
+ }
+ if b < 0x80 {
+ if i == binary.MaxVarintLen64-1 && b > 1 {
+ return x, overflow
+ }
+ return x | uint64(b)<<s, nil
+ }
+ x |= uint64(b&0x7f) << s
+ s += 7
+ }
+ return x, overflow
+}
+
+var overflow = errors.New("pkgbits: readUvarint overflows a 64-bit integer")
+
func (r *Decoder) rawVarint() int64 {
ux := r.rawUvarint()