]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link: remove allocation in decoding type name
authorCherry Mui <cherryyz@google.com>
Mon, 1 May 2023 16:54:27 +0000 (12:54 -0400)
committerCherry Mui <cherryyz@google.com>
Tue, 2 May 2023 17:29:09 +0000 (17:29 +0000)
The type name symbol is always from a Go object file and we never
change it. Convert the data to string using unsafe conversion
without allocation.

Linking cmd/go (on macOS/amd64),

name           old alloc/op   new alloc/op   delta
Deadcode_GC      1.25MB ± 0%    1.17MB ± 0%   -6.29%  (p=0.000 n=20+20)

name           old allocs/op  new allocs/op  delta
Deadcode_GC       8.98k ± 0%     0.10k ± 3%  -98.91%  (p=0.000 n=20+20)

Change-Id: I33117ad1f991e4f14ce0b38cceec50b041e3c0a4
Reviewed-on: https://go-review.googlesource.com/c/go/+/490915
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Cherry Mui <cherryyz@google.com>
Reviewed-by: Than McIntosh <thanm@google.com>
src/cmd/internal/goobj/objfile.go
src/cmd/link/internal/ld/deadcode.go
src/cmd/link/internal/ld/decodesym.go
src/cmd/link/internal/loader/loader.go

index 64d453abdc52725fbea7f64a03bdd41aa5a21471..c9d7ca434c4dfd4f1232e17f7a2f08c0e479773f 100644 (file)
@@ -853,6 +853,15 @@ func (r *Reader) Data(i uint32) []byte {
        return r.BytesAt(base+off, int(end-off))
 }
 
+// DataString returns the i-th symbol's data as a string.
+func (r *Reader) DataString(i uint32) string {
+       dataIdxOff := r.h.Offsets[BlkDataIdx] + i*4
+       base := r.h.Offsets[BlkData]
+       off := r.uint32At(dataIdxOff)
+       end := r.uint32At(dataIdxOff + 4)
+       return r.StringAt(base+off, end-off)
+}
+
 // NRefName returns the number of referenced symbol names.
 func (r *Reader) NRefName() int {
        return int(r.h.Offsets[BlkRefName+1]-r.h.Offsets[BlkRefName]) / RefNameSize
index c80bacd92c330c84e406da628e5e7296c9327620..e7028d3b544a1ac031f04391da1c7f70d47211a5 100644 (file)
@@ -487,7 +487,7 @@ func (d *deadcodePass) decodeIfaceMethod(ldr *loader.Loader, arch *sys.Arch, sym
 
 // Decode the method name stored in symbol symIdx. The symbol should contain just the bytes of a method name.
 func (d *deadcodePass) decodeGenericIfaceMethod(ldr *loader.Loader, symIdx loader.Sym) string {
-       return string(ldr.Data(symIdx))
+       return ldr.DataString(symIdx)
 }
 
 func (d *deadcodePass) decodetypeMethods(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, relocs *loader.Relocs) []methodsig {
index b0f4b875633ce068a176ee55e6a05497e7e0b52f..53ed6ccc86a251be34b948e87f4ff7bf37402bcb 100644 (file)
@@ -127,9 +127,13 @@ func decodetypeName(ldr *loader.Loader, symIdx loader.Sym, relocs *loader.Relocs
                return ""
        }
 
-       data := ldr.Data(r)
-       nameLen, nameLenLen := binary.Uvarint(data[1:])
-       return string(data[1+nameLenLen : 1+nameLenLen+int(nameLen)])
+       data := ldr.DataString(r)
+       n := 1 + binary.MaxVarintLen64
+       if len(data) < n {
+               n = len(data)
+       }
+       nameLen, nameLenLen := binary.Uvarint([]byte(data[1:n]))
+       return data[1+nameLenLen : 1+nameLenLen+int(nameLen)]
 }
 
 func decodetypeNameEmbedded(ldr *loader.Loader, symIdx loader.Sym, relocs *loader.Relocs, off int) bool {
index 5fcbf160e0f94ded8ee83074c45ac8d8b3508095..fa74dcede423038c9ef363fa72aaa54d02b35666 100644 (file)
@@ -1247,6 +1247,16 @@ func (l *Loader) Data(i Sym) []byte {
        return r.Data(li)
 }
 
+// Returns the symbol content of the i-th symbol as a string. i is global index.
+func (l *Loader) DataString(i Sym) string {
+       if l.IsExternal(i) {
+               pp := l.getPayload(i)
+               return string(pp.data)
+       }
+       r, li := l.toLocal(i)
+       return r.DataString(li)
+}
+
 // FreeData clears the symbol data of an external symbol, allowing the memory
 // to be freed earlier. No-op for non-external symbols.
 // i is global index.