Commit 0c84c4f1 authored by David Crawshaw's avatar David Crawshaw

cmd/link: combine all string data into one symbol

This CL introduces a mergestrings pass after the reachability
analysis to combine all reachable go.string."..." character data
symbols into a single symbol.

Shrinks juju by 1.2mb (1.5%).
Shrinks cmd/go by 0.5% when building without DWARF.
No noticable effect on linker speed.

Change-Id: I2ba3e60bf418f65766bda257f6ca9eea26d895b6
Reviewed-on: https://go-review.googlesource.com/20165
Run-TryBot: David Crawshaw <crawshaw@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
parent 7e92c86d
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package ld
import (
"cmd/internal/obj"
"strings"
)
// mergestrings merges all go.string.* character data into a single symbol.
//
// Combining string data symbols reduces the total binary size and
// makes deduplication possible.
func mergestrings() {
if Buildmode == BuildmodeShared {
return
}
strs := make([]*LSym, 0, 256)
seenStr := make(map[string]bool, 256) // symbol name -> in strs slice
relocsToStrs := make(map[*LSym][]*Reloc, 256) // string -> relocation to string
size := 0 // number of bytes in all strings
// Collect strings and relocations that point to strings.
for _, s := range Ctxt.Allsym {
if !s.Attr.Reachable() || s.Attr.Special() {
continue
}
for i := range s.R {
r := &s.R[i]
if r.Sym == nil {
continue
}
if !seenStr[r.Sym.Name] {
if !strings.HasPrefix(r.Sym.Name, "go.string.") {
continue
}
if strings.HasPrefix(r.Sym.Name, "go.string.hdr") {
continue
}
strs = append(strs, r.Sym)
seenStr[r.Sym.Name] = true
size += len(r.Sym.P)
}
relocsToStrs[r.Sym] = append(relocsToStrs[r.Sym], r)
}
}
// Put all string data into a single symbol and update the relocations.
alldata := Linklookup(Ctxt, "go.string.alldata", 0)
alldata.Type = obj.SGOSTRING
alldata.Attr |= AttrReachable
alldata.Size = int64(size)
alldata.P = make([]byte, 0, size)
for _, str := range strs {
off := len(alldata.P)
alldata.P = append(alldata.P, str.P...)
str.Attr.Set(AttrReachable, false)
for _, r := range relocsToStrs[str] {
r.Add += int64(off)
r.Sym = alldata
}
}
}
...@@ -197,6 +197,7 @@ func Ldmain() { ...@@ -197,6 +197,7 @@ func Ldmain() {
checkstrdata() checkstrdata()
deadcode() deadcode()
callgraph() callgraph()
mergestrings()
doelf() doelf()
if HEADTYPE == obj.Hdarwin { if HEADTYPE == obj.Hdarwin {
......
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