]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link: combine all string data into one symbol
authorDavid Crawshaw <crawshaw@golang.org>
Thu, 3 Mar 2016 15:51:30 +0000 (10:51 -0500)
committerDavid Crawshaw <crawshaw@golang.org>
Thu, 3 Mar 2016 19:57:16 +0000 (19:57 +0000)
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: Ian Lance Taylor <iant@golang.org>
src/cmd/link/internal/ld/mergestrings.go [new file with mode: 0644]
src/cmd/link/internal/ld/pobj.go

diff --git a/src/cmd/link/internal/ld/mergestrings.go b/src/cmd/link/internal/ld/mergestrings.go
new file mode 100644 (file)
index 0000000..0e16b36
--- /dev/null
@@ -0,0 +1,66 @@
+// 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
+               }
+       }
+}
index a66843fc11d985d9be421379b0e4e1e0a75bfbb8..d36dfc1b6835ae594ee629bfa3764dcdf4cb9fb2 100644 (file)
@@ -197,6 +197,7 @@ func Ldmain() {
        checkstrdata()
        deadcode()
        callgraph()
+       mergestrings()
 
        doelf()
        if HEADTYPE == obj.Hdarwin {