]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link: skip allocation when reading symbol name
authorDavid Crawshaw <crawshaw@golang.org>
Mon, 29 Feb 2016 00:59:33 +0000 (15:59 -0900)
committerDavid Crawshaw <crawshaw@golang.org>
Mon, 29 Feb 2016 19:30:48 +0000 (19:30 +0000)
The object file reader in cmd/link reads the symbol name into a scratch
[]byte, converts it to a string, and then does a substring replacement.
Instead, this CL does the replacement on the []byte into the scratch
space and then creates the final string.

Linking godoc without DWARF, best of ten, shows a ~10% improvement.

tip:           real 0m1.099s user 0m1.541s
this:          real 0m0.990s user 0m1.280s

This is part of an attempt to make suffixarray string deduping
come out as a wash, but it's not there yet:

cl/19987:      real 0m1.335s user 0m1.794s
cl/19987+this: real 0m1.225s user 0m1.540s

Change-Id: Idf061fdfbd7f08aa3a1f5933d3f111fdd1659210
Reviewed-on: https://go-review.googlesource.com/20025
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: David Crawshaw <crawshaw@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
src/cmd/link/internal/ld/objfile.go

index b04244f3cc98ea4a45fa1a55c908e00994eef135..11cdf91d74927209ca297684cd28240d60416079 100644 (file)
@@ -165,7 +165,7 @@ func readsym(ctxt *Link, f *obj.Biobuf, pkg string, pn string) {
                log.Fatalf("readsym out of sync")
        }
        t := rdint(f)
-       name := expandpkg(rdstring(f), pkg)
+       name := rdsymName(f, pkg)
        v := rdint(f)
        if v != 0 && v != 1 {
                log.Fatalf("invalid symbol version %d", v)
@@ -424,11 +424,17 @@ func rduint8(f *obj.Biobuf) uint8 {
        return uint8(n)
 }
 
+// rdBuf is used by rdstring and rdsymName as scratch for reading strings.
+var rdBuf []byte
+var emptyPkg = []byte(`"".`)
+
 func rdstring(f *obj.Biobuf) string {
-       n := rdint64(f)
-       p := make([]byte, n)
-       obj.Bread(f, p)
-       return string(p)
+       n := rdint(f)
+       if len(rdBuf) < n {
+               rdBuf = make([]byte, n)
+       }
+       obj.Bread(f, rdBuf[:n])
+       return string(rdBuf[:n])
 }
 
 var (
@@ -452,25 +458,48 @@ func rddata(f *obj.Biobuf) []byte {
        return p
 }
 
-var symbuf []byte
-
-func rdsym(ctxt *Link, f *obj.Biobuf, pkg string) *LSym {
+// rdsymName reads a symbol name, replacing all "". with pkg.
+func rdsymName(f *obj.Biobuf, pkg string) string {
        n := rdint(f)
        if n == 0 {
                rdint64(f)
-               return nil
+               return ""
        }
 
-       if len(symbuf) < n {
-               symbuf = make([]byte, n)
+       if len(rdBuf) < n {
+               rdBuf = make([]byte, n, 2*n)
+       }
+       origName := rdBuf[:n]
+       obj.Bread(f, origName)
+       adjName := rdBuf[n:n]
+       for {
+               i := bytes.Index(origName, emptyPkg)
+               if i == -1 {
+                       adjName = append(adjName, origName...)
+                       break
+               }
+               adjName = append(adjName, origName[:i]...)
+               adjName = append(adjName, pkg...)
+               adjName = append(adjName, '.')
+               origName = origName[i+len(emptyPkg):]
+       }
+       name := string(adjName)
+       if len(adjName) > len(rdBuf) {
+               rdBuf = adjName // save the larger buffer for reuse
+       }
+       return name
+}
+
+func rdsym(ctxt *Link, f *obj.Biobuf, pkg string) *LSym {
+       name := rdsymName(f, pkg)
+       if name == "" {
+               return nil
        }
-       obj.Bread(f, symbuf[:n])
-       p := string(symbuf[:n])
        v := rdint(f)
        if v != 0 {
                v = ctxt.Version
        }
-       s := Linklookup(ctxt, expandpkg(p, pkg), v)
+       s := Linklookup(ctxt, name, v)
 
        if v == 0 && s.Name[0] == '$' && s.Type == 0 {
                if strings.HasPrefix(s.Name, "$f32.") {