From 6e8da3febb8508ea8ae70ed5c3e6fed36cf73b5f Mon Sep 17 00:00:00 2001 From: David Chase Date: Tue, 15 Nov 2022 14:23:21 -0500 Subject: [PATCH] internal/pkgbits: port small optimization from compiler to tools Tools version of https://go.dev/cl/435336 I believe this helped the compiler (though I don't see the benchmark). We probably need benchmarks for tools, too. Change-Id: I3450ecb82fcef7050f28a4cffcbc224972680f36 Reviewed-on: https://go-review.googlesource.com/c/tools/+/450678 gopls-CI: kokoro TryBot-Result: Gopher Robot Run-TryBot: David Chase Reviewed-by: Matthew Dempsky --- internal/pkgbits/decoder.go | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/internal/pkgbits/decoder.go b/internal/pkgbits/decoder.go index 297e5b043a..3205c9a16c 100644 --- a/internal/pkgbits/decoder.go +++ b/internal/pkgbits/decoder.go @@ -6,6 +6,7 @@ package pkgbits import ( "encoding/binary" + "errors" "fmt" "go/constant" "go/token" @@ -248,11 +249,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)<