1
0
mirror of https://github.com/golang/go synced 2024-11-19 15:05:00 -07:00

cmd/compile: allow linker to drop string headers when not needed

Compiling a simple file containing a slice of 100,000 strings,
the size of the resulting binary dropped from 5,896,224 bytes
to 3,495,968 bytes, which is the expected 2,400,000 bytes,
give or take.

Fixes #7384.

Change-Id: I3e551b5a1395b523a41b33518d81a1bf28da0906
Reviewed-on: https://go-review.googlesource.com/11698
Reviewed-by: Austin Clements <austin@google.com>
This commit is contained in:
Russ Cox 2015-06-29 13:50:30 -04:00
parent 3b6e86f48a
commit e8f2eb4349

View File

@ -200,7 +200,7 @@ func duintptr(s *Sym, off int, v uint64) int {
var stringsym_gen int var stringsym_gen int
func stringsym(s string) *Sym { func stringsym(s string) (hdr, data *Sym) {
var symname string var symname string
var pkg *Pkg var pkg *Pkg
if len(s) > 100 { if len(s) > 100 {
@ -217,36 +217,44 @@ func stringsym(s string) *Sym {
pkg = gostringpkg pkg = gostringpkg
} }
sym := Pkglookup(symname, pkg) symhdr := Pkglookup("hdr."+symname, pkg)
symdata := Pkglookup(symname, pkg)
// SymUniq flag indicates that data is generated already // SymUniq flag indicates that data is generated already
if sym.Flags&SymUniq != 0 { if symhdr.Flags&SymUniq != 0 {
return sym return symhdr, symdata
} }
sym.Flags |= SymUniq symhdr.Flags |= SymUniq
sym.Def = newname(sym) symhdr.Def = newname(symhdr)
off := 0
// string header // string header
off = dsymptr(sym, off, sym, Widthptr+Widthint) off := 0
off = duintxx(sym, off, uint64(len(s)), Widthint) off = dsymptr(symhdr, off, symdata, 0)
off = duintxx(symhdr, off, uint64(len(s)), Widthint)
ggloblsym(symhdr, int32(off), obj.DUPOK|obj.RODATA|obj.LOCAL)
// string data // string data
if symdata.Flags&SymUniq != 0 {
return symhdr, symdata
}
symdata.Flags |= SymUniq
symdata.Def = newname(symdata)
off = 0
var m int var m int
for n := 0; n < len(s); n += m { for n := 0; n < len(s); n += m {
m = 8 m = 8
if m > len(s)-n { if m > len(s)-n {
m = len(s) - n m = len(s) - n
} }
off = dsname(sym, off, s[n:n+m]) off = dsname(symdata, off, s[n:n+m])
} }
off = duint8(sym, off, 0) // terminating NUL for runtime off = duint8(symdata, off, 0) // terminating NUL for runtime
off = (off + Widthptr - 1) &^ (Widthptr - 1) // round to pointer alignment off = (off + Widthptr - 1) &^ (Widthptr - 1) // round to pointer alignment
ggloblsym(sym, int32(off), obj.DUPOK|obj.RODATA|obj.LOCAL) ggloblsym(symdata, int32(off), obj.DUPOK|obj.RODATA|obj.LOCAL)
return sym return symhdr, symdata
} }
var slicebytes_gen int var slicebytes_gen int
@ -299,22 +307,22 @@ func dstringptr(s *Sym, off int, str string) int {
} }
func Datastring(s string, a *obj.Addr) { func Datastring(s string, a *obj.Addr) {
sym := stringsym(s) _, symdata := stringsym(s)
a.Type = obj.TYPE_MEM a.Type = obj.TYPE_MEM
a.Name = obj.NAME_EXTERN a.Name = obj.NAME_EXTERN
a.Sym = Linksym(sym) a.Sym = Linksym(symdata)
a.Node = sym.Def a.Node = symdata.Def
a.Offset = int64(Widthptr) + int64(Widthint) // skip header a.Offset = 0
a.Etype = Simtype[TINT] a.Etype = Simtype[TINT]
} }
func datagostring(sval string, a *obj.Addr) { func datagostring(sval string, a *obj.Addr) {
sym := stringsym(sval) symhdr, _ := stringsym(sval)
a.Type = obj.TYPE_MEM a.Type = obj.TYPE_MEM
a.Name = obj.NAME_EXTERN a.Name = obj.NAME_EXTERN
a.Sym = Linksym(sym) a.Sym = Linksym(symhdr)
a.Node = sym.Def a.Node = symhdr.Def
a.Offset = 0 // header a.Offset = 0
a.Etype = TSTRING a.Etype = TSTRING
} }