]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.link] cmd/link: only do name expansion when needed
authorCherry Zhang <cherryyz@google.com>
Mon, 18 May 2020 22:20:18 +0000 (18:20 -0400)
committerCherry Zhang <cherryyz@google.com>
Tue, 19 May 2020 14:53:39 +0000 (14:53 +0000)
Most Go objects are compiled with known package path, so the
symbol name is already fully expanded. Nevertheless, currently
in the linker strings.Replace is called unconditionally, and most
of the time it doesn't do anything.

This CL records a per-object flag in the object file, and do the
name expansion only when the name is not expanded at compile time.

This gives small speedups for the linker. Linking cmd/compile:

name                    old time/op    new time/op    delta
Loadlib                   35.1ms ± 2%    32.8ms ± 4%   -6.43%  (p=0.008 n=5+5)
Symtab                    15.8ms ± 2%    14.0ms ± 8%  -11.45%  (p=0.008 n=5+5)
TotalTime                  399ms ± 1%     385ms ± 2%   -3.63%  (p=0.008 n=5+5)

Change-Id: I735084971a051cd9be4284ad294c284cd5b545f4
Reviewed-on: https://go-review.googlesource.com/c/go/+/234490
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
src/cmd/internal/goobj2/objfile.go
src/cmd/internal/obj/objfile2.go
src/cmd/link/internal/loader/loader.go

index fde482e07996800cb137daa4069ab3ba433ca56b..dc5174f85e22e0eddc15b5c56778db13ba407443 100644 (file)
@@ -228,7 +228,8 @@ const SymSize = stringRefSize + 2 + 1 + 1 + 4 + 4
 const SymABIstatic = ^uint16(0)
 
 const (
-       ObjFlagShared = 1 << iota
+       ObjFlagShared            = 1 << iota // this object is built with -shared
+       ObjFlagNeedNameExpansion             // the linker needs to expand `"".` to package path in symbol names
 )
 
 const (
@@ -675,3 +676,6 @@ func (r *Reader) ReadOnly() bool {
 func (r *Reader) Flags() uint32 {
        return r.h.Flags
 }
+
+func (r *Reader) Shared() bool            { return r.Flags()&ObjFlagShared != 0 }
+func (r *Reader) NeedNameExpansion() bool { return r.Flags()&ObjFlagNeedNameExpansion != 0 }
index 0b3b2be41b9de652be9210a922703b657b31e279..c28ae569d339fddbae2ae4701efdd441add33286 100644 (file)
@@ -38,6 +38,9 @@ func WriteObjFile(ctxt *Link, b *bio.Writer, pkgpath string) {
        if ctxt.Flag_shared {
                flags |= goobj2.ObjFlagShared
        }
+       if pkgpath == "" {
+               flags |= goobj2.ObjFlagNeedNameExpansion
+       }
        h := goobj2.Header{
                Magic:       goobj2.Magic,
                Fingerprint: ctxt.Fingerprint,
index 5696c511007c18f76f14552aac361bb51d7b77b2..26b17ce007be9a44dd18163cc7d9b748ef1d5049 100644 (file)
@@ -661,7 +661,11 @@ func (l *Loader) SymName(i Sym) string {
                return pp.name
        }
        r, li := l.toLocal(i)
-       return strings.Replace(r.Sym(li).Name(r.Reader), "\"\".", r.pkgprefix, -1)
+       name := r.Sym(li).Name(r.Reader)
+       if !r.NeedNameExpansion() {
+               return name
+       }
+       return strings.Replace(name, "\"\".", r.pkgprefix, -1)
 }
 
 // Returns the version of the i-th symbol.
@@ -843,7 +847,7 @@ func (l *Loader) AttrShared(i Sym) bool {
                // might make more sense to copy the flag value out of the
                // object into a larger bitmap during preload.
                r, _ := l.toLocal(i)
-               return (r.Flags() & goobj2.ObjFlagShared) != 0
+               return r.Shared()
        }
        return l.attrShared.Has(l.extIndex(i))
 }
@@ -1948,9 +1952,13 @@ func (l *Loader) preloadSyms(r *oReader, kind int) {
                panic("preloadSyms: bad kind")
        }
        l.growAttrBitmaps(len(l.objSyms) + int(end-start))
+       needNameExpansion := r.NeedNameExpansion()
        for i := start; i < end; i++ {
                osym := r.Sym(i)
-               name := strings.Replace(osym.Name(r.Reader), "\"\".", r.pkgprefix, -1)
+               name := osym.Name(r.Reader)
+               if needNameExpansion {
+                       name = strings.Replace(name, "\"\".", r.pkgprefix, -1)
+               }
                v := abiToVer(osym.ABI(), r.version)
                dupok := osym.Dupok()
                gi, added := l.AddSym(name, v, r, i, kind, dupok, sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type())])
@@ -1998,9 +2006,13 @@ func (l *Loader) LoadNonpkgSyms(arch *sys.Arch) {
 
 func loadObjRefs(l *Loader, r *oReader, arch *sys.Arch) {
        ndef := uint32(r.NSym() + r.NNonpkgdef())
+       needNameExpansion := r.NeedNameExpansion()
        for i, n := uint32(0), uint32(r.NNonpkgref()); i < n; i++ {
                osym := r.Sym(ndef + i)
-               name := strings.Replace(osym.Name(r.Reader), "\"\".", r.pkgprefix, -1)
+               name := osym.Name(r.Reader)
+               if needNameExpansion {
+                       name = strings.Replace(name, "\"\".", r.pkgprefix, -1)
+               }
                v := abiToVer(osym.ABI(), r.version)
                r.syms[ndef+i] = l.LookupOrCreateSym(name, v)
                gi := r.syms[ndef+i]
@@ -2109,7 +2121,10 @@ func (l *Loader) cloneToExternal(symIdx Sym) {
        // Read the particulars from object.
        r, li := l.toLocal(symIdx)
        osym := r.Sym(li)
-       sname := strings.Replace(osym.Name(r.Reader), "\"\".", r.pkgprefix, -1)
+       sname := osym.Name(r.Reader)
+       if r.NeedNameExpansion() {
+               sname = strings.Replace(sname, "\"\".", r.pkgprefix, -1)
+       }
        sver := abiToVer(osym.ABI(), r.version)
        skind := sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type())]