]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link, cmd/compile: typelink sorting in linker
authorDavid Crawshaw <crawshaw@golang.org>
Mon, 4 Apr 2016 17:07:24 +0000 (13:07 -0400)
committerDavid Crawshaw <crawshaw@golang.org>
Mon, 18 Apr 2016 19:20:37 +0000 (19:20 +0000)
Instead of writing out the type almost twice in the symbol name,
teach the linker how to sort typelink symbols by their contents.

This ~halves the size of typelink symbol names, which helps very
large (6KB) names like those mentioned in #15104.

This does not increase the total sorting work done by the linker,
and makes it possible to use shorter symbol names for types. See
the follow-on CL 21583.

Change-Id: Ie5807565ed07d31bc477d20f60e4c0b47144f337
Reviewed-on: https://go-review.googlesource.com/21457
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/cmd/compile/internal/gc/reflect.go
src/cmd/link/internal/ld/data.go
src/cmd/link/internal/ld/decodesym.go

index f782ce097488556f77431a9cf5f007fca64b4767..5031045c64eff2db968e04c678b3739594e27285 100644 (file)
@@ -912,16 +912,7 @@ func tracksym(t *Type, f *Field) *Sym {
 }
 
 func typelinkLSym(t *Type) *obj.LSym {
-       // %-uT is what the generated Type's string field says.
-       // It uses (ambiguous) package names instead of import paths.
-       // %-T is the complete, unambiguous type name.
-       // We want the types to end up sorted by string field,
-       // so use that first in the name, and then add :%-T to
-       // disambiguate. We use a tab character as the separator to
-       // ensure the types appear sorted by their string field. The
-       // names are a little long but they are discarded by the linker
-       // and do not end up in the symbol table of the final binary.
-       name := "go.typelink." + Tconv(t, FmtLeft|FmtUnsigned) + "\t" + Tconv(t, FmtLeft)
+       name := "go.typelink." + Tconv(t, FmtLeft) // complete, unambiguous type name
        return obj.Linklookup(Ctxt, name, 0)
 }
 
index 105503f6ef34f5009e40af855028a1ab25eeeb18..8e2cf99877444388d5d5334c362ae6e6b05d8a1e 100644 (file)
@@ -32,6 +32,7 @@
 package ld
 
 import (
+       "bytes"
        "cmd/internal/gcprog"
        "cmd/internal/obj"
        "cmd/internal/sys"
@@ -1199,6 +1200,13 @@ func (d dataSlice) Less(i, j int) bool {
                return s1.Size < s2.Size
        }
 
+       // Sort typelinks by the string field.
+       if strings.HasPrefix(s1.Name, "go.typelink.") && strings.HasPrefix(s2.Name, "go.typelink.") {
+               s1n := decodetype_string(s1.Lsym.R[0].Sym)
+               s2n := decodetype_string(s2.Lsym.R[0].Sym)
+               return bytes.Compare(s1n, s2n) < 0
+       }
+
        return s1.Name < s2.Name
 }
 
index 5eb20c2fb2241fd5dceed98928d33d2f3b0dfb8b..b1c55cf787f05afb1966ba6106982be4c5920683 100644 (file)
@@ -211,6 +211,18 @@ func decodetype_structfieldarrayoff(s *LSym, i int) int {
        return off
 }
 
+// decodetype_string returns the contents of an rtype's string field.
+func decodetype_string(s *LSym) []byte {
+       off := 4*SysArch.PtrSize + 8
+       strlen := int64(decode_inuxi(s.P[off+SysArch.PtrSize:], SysArch.IntSize))
+
+       r := decode_reloc(s, int32(off))
+       if r == nil {
+               return nil
+       }
+       return r.Sym.P[r.Add : r.Add+strlen]
+}
+
 // decodetype_name decodes the name from a reflect.name.
 func decodetype_name(s *LSym, off int) string {
        r := decode_reloc(s, int32(off))