diff options
| author | David Chase <drchase@google.com> | 2022-09-27 14:37:35 -0400 |
|---|---|---|
| committer | David Chase <drchase@google.com> | 2022-09-27 20:58:46 +0000 |
| commit | caa8e1f97788d4276276d68610fadc6179a022ee (patch) | |
| tree | 03ac749b283a8498169819642eb1c9e6891f2302 /src/internal/pkgbits/decoder.go | |
| parent | e8afb2911125ad65ddc02f7b83ab78a3e2f573b7 (diff) | |
| download | go-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.go | 31 |
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() |
