From ab1253b59ae7bfe5a064bf299bc896a65cc5a027 Mon Sep 17 00:00:00 2001 From: Cherry Zhang Date: Fri, 7 Feb 2020 11:02:42 -0500 Subject: [PATCH] [dev.link] cmd/link: don't read symbol name if not needed Most of the time of goobj2.Sym.Read is spent in reading the symbol name. Sometimes the name is not needed, so don't read it. This brings the linking time pretty much back to the old linker. On my Mac, $ time go build cmd/compile # (new) real 0m1.016s user 0m1.164s sys 0m0.297s $ time go-tip build cmd/compile # (old) real 0m0.980s user 0m1.229s sys 0m0.309s Again, this is a bit ugly. Maybe we want to consider moving symbol names out of Sym, to a separate section of the object file? Change-Id: Ia9085c15aa4d614b7eae126e71a79d6806c75055 Reviewed-on: https://go-review.googlesource.com/c/go/+/218480 Run-TryBot: Cherry Zhang TryBot-Result: Gobot Gobot Reviewed-by: Jeremy Faller Reviewed-by: Than McIntosh --- src/cmd/internal/goobj2/objfile.go | 10 ++++++++++ src/cmd/link/internal/loader/loader.go | 20 ++++---------------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/cmd/internal/goobj2/objfile.go b/src/cmd/internal/goobj2/objfile.go index 34a686bb1a..a903a102c3 100644 --- a/src/cmd/internal/goobj2/objfile.go +++ b/src/cmd/internal/goobj2/objfile.go @@ -225,6 +225,16 @@ func (s *Sym) Read(r *Reader, off uint32) { s.Siz = r.uint32At(off + 8) } +// Read fields other than the symbol name. The name is not necessary +// in some cases, and most of the time spent in Read is reading the +// name. +func (s *Sym) ReadWithoutName(r *Reader, off uint32) { + s.ABI = r.uint16At(off + 4) + s.Type = r.uint8At(off + 6) + s.Flag = r.uint8At(off + 7) + s.Siz = r.uint32At(off + 8) +} + func (s *Sym) ReadFlag(r *Reader, off uint32) { s.Flag = r.uint8At(off + 7) } diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go index 8014d83aba..45ddef9574 100644 --- a/src/cmd/link/internal/loader/loader.go +++ b/src/cmd/link/internal/loader/loader.go @@ -343,7 +343,7 @@ func (l *Loader) AddSym(name string, ver int, r *oReader, li int, dupok bool, ty } oldr, oldli := l.toLocal(oldi) oldsym := goobj2.Sym{} - oldsym.Read(oldr.Reader, oldr.SymOff(oldli)) + oldsym.ReadWithoutName(oldr.Reader, oldr.SymOff(oldli)) if oldsym.Dupok() { return oldi, false } @@ -615,7 +615,7 @@ func (l *Loader) SymVersion(i Sym) int { } r, li := l.toLocal(i) osym := goobj2.Sym{} - osym.Read(r.Reader, r.SymOff(li)) + osym.ReadWithoutName(r.Reader, r.SymOff(li)) return int(abiToVer(osym.ABI, r.version)) } @@ -630,7 +630,7 @@ func (l *Loader) SymType(i Sym) sym.SymKind { } r, li := l.toLocal(i) osym := goobj2.Sym{} - osym.Read(r.Reader, r.SymOff(li)) + osym.ReadWithoutName(r.Reader, r.SymOff(li)) return sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type)] } @@ -1766,10 +1766,6 @@ func loadObjSyms(l *Loader, syms *sym.Symbols, r *oReader) int { continue } ver := abiToVer(osym.ABI, r.version) - if osym.ABI != goobj2.SymABIstatic && l.symsByName[ver][name] != gi { - continue - } - t := sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type)] if t == sym.SXREF { log.Fatalf("bad sxref") @@ -1987,11 +1983,7 @@ func loadObjFull(l *Loader, r *oReader) { } osym := goobj2.Sym{} - osym.Read(r.Reader, r.SymOff(i)) - name := strings.Replace(osym.Name, "\"\".", r.pkgprefix, -1) - if name == "" { - continue - } + osym.ReadWithoutName(r.Reader, r.SymOff(i)) dupok := osym.Dupok() if dupok && isdup { if l.attrReachable.has(gi) { @@ -2014,10 +2006,6 @@ func loadObjFull(l *Loader, r *oReader) { if s == nil { continue } - if s.Name != name { // Sanity check. We can remove it in the final version. - fmt.Println("name mismatch:", lib, i, s.Name, name) - panic("name mismatch") - } local := osym.Local() makeTypelink := osym.Typelink()