Commit 4140da7b authored by David Crawshaw's avatar David Crawshaw

cmd/link, cmd/compile: typelink sorting in linker

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/21457Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
parent 2e2df78a
......@@ -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)
}
......
......@@ -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
}
......
......@@ -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))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment