]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: don't create 2 Sym's and 2 Node's for every string
authorIan Lance Taylor <iant@golang.org>
Thu, 17 Mar 2016 05:22:58 +0000 (22:22 -0700)
committerIan Lance Taylor <iant@golang.org>
Thu, 17 Mar 2016 16:15:11 +0000 (16:15 +0000)
For every string constant the compiler was creating 2 Sym's and 2
Node's.  It would never refer to them again, but would keep them alive
in gostringpkg.  This changes the code to just use obj.LSym's instead.

When compiling x/tools/go/types, this yields about a 15% reduction in
the number of calls to newname and a 3% reduction in the total number of
Node objects.  Unfortunately I couldn't see any change in compile time,
but reducing memory usage is desirable anyhow.

Passes toolstash -cmp.

Change-Id: I24f1cb1e6cff0a3afba4ca66f7166874917a036b
Reviewed-on: https://go-review.googlesource.com/20792
Reviewed-by: David Crawshaw <crawshaw@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/cmd/compile/internal/gc/go.go
src/cmd/compile/internal/gc/gsubr.go
src/cmd/compile/internal/gc/main.go
src/cmd/compile/internal/gc/obj.go
src/cmd/compile/internal/gc/reflect.go
src/cmd/compile/internal/gc/ssa.go
src/cmd/internal/obj/link.go

index 4473ee6cdfa3161944ef4f3cc1469ce622564641..6feb5fb661211dd91b20e61d9471ef831c94f1af 100644 (file)
@@ -249,8 +249,6 @@ var localpkg *Pkg // package being compiled
 
 var importpkg *Pkg // package being imported
 
-var gostringpkg *Pkg // fake pkg for Go strings
-
 var itabpkg *Pkg // fake pkg for itab cache
 
 var Runtimepkg *Pkg // package runtime
index efc48c76a163b864596dd7ea474452ae8acb5811..ddaa3f26d93c97fede864d1fcca0be4a85d85d1c 100644 (file)
@@ -234,10 +234,14 @@ func ggloblnod(nam *Node) {
 }
 
 func ggloblsym(s *Sym, width int32, flags int16) {
+       ggloblLSym(Linksym(s), width, flags)
+}
+
+func ggloblLSym(s *obj.LSym, width int32, flags int16) {
        p := Thearch.Gins(obj.AGLOBL, nil, nil)
        p.From.Type = obj.TYPE_MEM
        p.From.Name = obj.NAME_EXTERN
-       p.From.Sym = Linksym(s)
+       p.From.Sym = s
        if flags&obj.LOCAL != 0 {
                p.From.Sym.Local = true
                flags &= ^obj.LOCAL
index f4396d13e2b64143dfe7e401348ce9449f208425..63a0ab8ca9a3900f039bea55958260ae09f5405f 100644 (file)
@@ -122,11 +122,6 @@ func Main() {
        Runtimepkg.Name = "runtime"
 
        // pseudo-packages used in symbol tables
-       gostringpkg = mkpkg("go.string")
-
-       gostringpkg.Name = "go.string"
-       gostringpkg.Prefix = "go.string" // not go%2estring
-
        itabpkg = mkpkg("go.itab")
 
        itabpkg.Name = "go.itab"
index 91d0ac87d5b1d7cc4f527c8b521e15d8883cbd8a..6093d4ad6e20f3513d4134a43c151cbf43ecc1da 100644 (file)
@@ -159,12 +159,16 @@ func Linksym(s *Sym) *obj.LSym {
 }
 
 func duintxx(s *Sym, off int, v uint64, wid int) int {
+       return duintxxLSym(Linksym(s), off, v, wid)
+}
+
+func duintxxLSym(s *obj.LSym, off int, v uint64, wid int) int {
        // Update symbol data directly instead of generating a
        // DATA instruction that liblink will have to interpret later.
        // This reduces compilation time and memory usage.
        off = int(Rnd(int64(off), int64(wid)))
 
-       return int(obj.Setuintxx(Ctxt, Linksym(s), int64(off), v, int64(wid)))
+       return int(obj.Setuintxx(Ctxt, s, int64(off), v, int64(wid)))
 }
 
 func duint8(s *Sym, off int, v uint8) int {
@@ -183,7 +187,18 @@ func duintptr(s *Sym, off int, v uint64) int {
        return duintxx(s, off, v, Widthptr)
 }
 
-func stringsym(s string) (hdr, data *Sym) {
+// stringConstantSyms holds the pair of symbols we create for a
+// constant string.
+type stringConstantSyms struct {
+       hdr  *obj.LSym // string header
+       data *obj.LSym // actual string data
+}
+
+// stringConstants maps from the symbol name we use for the string
+// contents to the pair of linker symbols for that string.
+var stringConstants = make(map[string]stringConstantSyms, 100)
+
+func stringsym(s string) (hdr, data *obj.LSym) {
        var symname string
        if len(s) > 100 {
                // Huge strings are hashed to avoid long names in object files.
@@ -197,31 +212,34 @@ func stringsym(s string) (hdr, data *Sym) {
                symname = strconv.Quote(s)
        }
 
-       symhdr := Pkglookup("hdr."+symname, gostringpkg)
-       symdata := Pkglookup(symname, gostringpkg)
+       const prefix = "go.string."
+       symdataname := prefix + symname
+
+       // All the strings have the same prefix, so ignore it for map
+       // purposes, but use a slice of the symbol name string to
+       // reduce long-term memory overhead.
+       key := symdataname[len(prefix):]
 
-       // SymUniq flag indicates that data is generated already
-       if symhdr.Flags&SymUniq != 0 {
-               return symhdr, symdata
+       if syms, ok := stringConstants[key]; ok {
+               return syms.hdr, syms.data
        }
-       symhdr.Flags |= SymUniq
-       symhdr.Def = newname(symhdr)
+
+       symhdrname := "go.string.hdr." + symname
+
+       symhdr := obj.Linklookup(Ctxt, symhdrname, 0)
+       symdata := obj.Linklookup(Ctxt, symdataname, 0)
+
+       stringConstants[key] = stringConstantSyms{symhdr, symdata}
 
        // string header
        off := 0
-       off = dsymptr(symhdr, off, symdata, 0)
-       off = duintxx(symhdr, off, uint64(len(s)), Widthint)
-       ggloblsym(symhdr, int32(off), obj.DUPOK|obj.RODATA|obj.LOCAL)
+       off = dsymptrLSym(symhdr, off, symdata, 0)
+       off = duintxxLSym(symhdr, off, uint64(len(s)), Widthint)
+       ggloblLSym(symhdr, int32(off), obj.DUPOK|obj.RODATA|obj.LOCAL)
 
        // string data
-       if symdata.Flags&SymUniq != 0 {
-               return symhdr, symdata
-       }
-       symdata.Flags |= SymUniq
-       symdata.Def = newname(symdata)
-
-       off = dsname(symdata, 0, s)
-       ggloblsym(symdata, int32(off), obj.DUPOK|obj.RODATA|obj.LOCAL)
+       off = dsnameLSym(symdata, 0, s)
+       ggloblLSym(symdata, int32(off), obj.DUPOK|obj.RODATA|obj.LOCAL)
 
        return symhdr, symdata
 }
@@ -250,8 +268,7 @@ func Datastring(s string, a *obj.Addr) {
        _, symdata := stringsym(s)
        a.Type = obj.TYPE_MEM
        a.Name = obj.NAME_EXTERN
-       a.Sym = Linksym(symdata)
-       a.Node = symdata.Def
+       a.Sym = symdata
        a.Offset = 0
        a.Etype = uint8(Simtype[TINT])
 }
@@ -260,8 +277,7 @@ func datagostring(sval string, a *obj.Addr) {
        symhdr, _ := stringsym(sval)
        a.Type = obj.TYPE_MEM
        a.Name = obj.NAME_EXTERN
-       a.Sym = Linksym(symhdr)
-       a.Node = symhdr.Def
+       a.Sym = symhdr
        a.Offset = 0
        a.Etype = uint8(TSTRING)
 }
@@ -279,19 +295,27 @@ func dgostrlitptr(s *Sym, off int, lit *string) int {
        }
        off = int(Rnd(int64(off), int64(Widthptr)))
        symhdr, _ := stringsym(*lit)
-       Linksym(s).WriteAddr(Ctxt, int64(off), Widthptr, Linksym(symhdr), 0)
+       Linksym(s).WriteAddr(Ctxt, int64(off), Widthptr, symhdr, 0)
        off += Widthptr
        return off
 }
 
 func dsname(s *Sym, off int, t string) int {
-       Linksym(s).WriteString(Ctxt, int64(off), len(t), t)
+       return dsnameLSym(Linksym(s), off, t)
+}
+
+func dsnameLSym(s *obj.LSym, off int, t string) int {
+       s.WriteString(Ctxt, int64(off), len(t), t)
        return off + len(t)
 }
 
 func dsymptr(s *Sym, off int, x *Sym, xoff int) int {
+       return dsymptrLSym(Linksym(s), off, Linksym(x), xoff)
+}
+
+func dsymptrLSym(s *obj.LSym, off int, x *obj.LSym, xoff int) int {
        off = int(Rnd(int64(off), int64(Widthptr)))
-       Linksym(s).WriteAddr(Ctxt, int64(off), Widthptr, Linksym(x), int64(xoff))
+       s.WriteAddr(Ctxt, int64(off), Widthptr, x, int64(xoff))
        off += Widthptr
        return off
 }
@@ -368,6 +392,6 @@ func gdatacomplex(nam *Node, cval *Mpcplx) {
 func gdatastring(nam *Node, sval string) {
        s := Linksym(nam.Sym)
        _, symdata := stringsym(sval)
-       s.WriteAddr(Ctxt, nam.Xoffset, Widthptr, Linksym(symdata), 0)
+       s.WriteAddr(Ctxt, nam.Xoffset, Widthptr, symdata, 0)
        s.WriteInt(Ctxt, nam.Xoffset+int64(Widthptr), Widthint, int64(len(sval)))
 }
index e72fa4fdcd131d7a987d9de5379fc16b0b46e4a9..a8d0c93cf56a520cde2bb8f5ffb952a61c4d0f31 100644 (file)
@@ -770,7 +770,7 @@ func dcommontype(s *Sym, ot int, t *Type) int {
                prefix = 1
        }
        _, symdata := stringsym(p) // string
-       ot = dsymptr(s, ot, symdata, prefix)
+       ot = dsymptrLSym(Linksym(s), ot, symdata, prefix)
        ot = duintxx(s, ot, uint64(len(p)-prefix), Widthint)
 
        return ot
index 716be35034e3db7a981fa2854b427a256d14b825..06e317eb0992ea2566137fbad25df2b56b2eddb2 100644 (file)
@@ -3845,7 +3845,14 @@ func AddAux2(a *obj.Addr, v *ssa.Value, offset int64) {
        switch sym := v.Aux.(type) {
        case *ssa.ExternSymbol:
                a.Name = obj.NAME_EXTERN
-               a.Sym = Linksym(sym.Sym.(*Sym))
+               switch s := sym.Sym.(type) {
+               case *Sym:
+                       a.Sym = Linksym(s)
+               case *obj.LSym:
+                       a.Sym = s
+               default:
+                       v.Fatalf("ExternSymbol.Sym is %T", s)
+               }
        case *ssa.ArgSymbol:
                n := sym.Node.(*Node)
                a.Name = obj.NAME_PARAM
index 7da7adae5de03362d82214ad8f643ae5543435b5..8cae1255cd0e5549a3a2492141a40cadab5ce3b4 100644 (file)
@@ -343,6 +343,12 @@ type LSym struct {
        R      []Reloc
 }
 
+// The compiler needs LSym to satisfy fmt.Stringer, because it stores
+// an LSym in ssa.ExternSymbol.
+func (s *LSym) String() string {
+       return s.Name
+}
+
 type Pcln struct {
        Pcsp        Pcdata
        Pcfile      Pcdata