1
0
mirror of https://github.com/golang/go synced 2024-11-24 20:00:10 -07:00

cmd/link: skip allocation when reading symbol name

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>
This commit is contained in:
David Crawshaw 2016-02-28 15:59:33 -09:00
parent 6d0b551931
commit 07ccc21295

View File

@ -165,7 +165,7 @@ func readsym(ctxt *Link, f *obj.Biobuf, pkg string, pn string) {
log.Fatalf("readsym out of sync") log.Fatalf("readsym out of sync")
} }
t := rdint(f) t := rdint(f)
name := expandpkg(rdstring(f), pkg) name := rdsymName(f, pkg)
v := rdint(f) v := rdint(f)
if v != 0 && v != 1 { if v != 0 && v != 1 {
log.Fatalf("invalid symbol version %d", v) log.Fatalf("invalid symbol version %d", v)
@ -424,11 +424,17 @@ func rduint8(f *obj.Biobuf) uint8 {
return uint8(n) 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 { func rdstring(f *obj.Biobuf) string {
n := rdint64(f) n := rdint(f)
p := make([]byte, n) if len(rdBuf) < n {
obj.Bread(f, p) rdBuf = make([]byte, n)
return string(p) }
obj.Bread(f, rdBuf[:n])
return string(rdBuf[:n])
} }
var ( var (
@ -452,25 +458,48 @@ func rddata(f *obj.Biobuf) []byte {
return p return p
} }
var symbuf []byte // rdsymName reads a symbol name, replacing all "". with pkg.
func rdsymName(f *obj.Biobuf, pkg string) string {
func rdsym(ctxt *Link, f *obj.Biobuf, pkg string) *LSym {
n := rdint(f) n := rdint(f)
if n == 0 { if n == 0 {
rdint64(f) rdint64(f)
return nil return ""
} }
if len(symbuf) < n { if len(rdBuf) < n {
symbuf = make([]byte, 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) v := rdint(f)
if v != 0 { if v != 0 {
v = ctxt.Version 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 v == 0 && s.Name[0] == '$' && s.Type == 0 {
if strings.HasPrefix(s.Name, "$f32.") { if strings.HasPrefix(s.Name, "$f32.") {