Commit 2e90192b authored by Shahar Kohanim's avatar Shahar Kohanim Committed by David Crawshaw

cmd/link: refactor symbol lookup

Calling the read only Linkrlookup will now not cause the name
string to escape. So a lookup can be performed on a []byte
casted to a string without allocating. This will help a followup
cl and it is also much simpler and cleaner.
Performance not impacted by this.

name       old s/op   new s/op   delta
LinkCmdGo  0.51 ± 6%  0.51 ± 5%   ~     (p=0.192 n=98+98)

Change-Id: I7846ba3160eb845a3a29cbf0be703c47369ece16
Reviewed-on: https://go-review.googlesource.com/21187Reviewed-by: 's avatarBrad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: 's avatarDavid Crawshaw <crawshaw@golang.org>
Run-TryBot: David Crawshaw <crawshaw@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 7e88826a
...@@ -450,7 +450,7 @@ func ldelf(f *obj.Biobuf, pkg string, length int64, pn string) { ...@@ -450,7 +450,7 @@ func ldelf(f *obj.Biobuf, pkg string, length int64, pn string) {
fmt.Fprintf(&Bso, "%5.2f ldelf %s\n", obj.Cputime(), pn) fmt.Fprintf(&Bso, "%5.2f ldelf %s\n", obj.Cputime(), pn)
} }
Ctxt.Version++ Ctxt.IncVersion()
base := int32(obj.Boffset(f)) base := int32(obj.Boffset(f))
var add uint64 var add uint64
......
...@@ -429,7 +429,7 @@ func ldmacho(f *obj.Biobuf, pkg string, length int64, pn string) { ...@@ -429,7 +429,7 @@ func ldmacho(f *obj.Biobuf, pkg string, length int64, pn string) {
var rp *Reloc var rp *Reloc
var name string var name string
Ctxt.Version++ Ctxt.IncVersion()
base := obj.Boffset(f) base := obj.Boffset(f)
if obj.Bread(f, hdr[:]) != len(hdr) { if obj.Bread(f, hdr[:]) != len(hdr) {
goto bad goto bad
......
...@@ -133,7 +133,7 @@ func ldpe(f *obj.Biobuf, pkg string, length int64, pn string) { ...@@ -133,7 +133,7 @@ func ldpe(f *obj.Biobuf, pkg string, length int64, pn string) {
} }
var sect *PeSect var sect *PeSect
Ctxt.Version++ Ctxt.IncVersion()
base := int32(obj.Boffset(f)) base := int32(obj.Boffset(f))
peobj := new(PeObj) peobj := new(PeObj)
......
...@@ -171,11 +171,8 @@ type Link struct { ...@@ -171,11 +171,8 @@ type Link struct {
Windows int32 Windows int32
Goroot string Goroot string
// Map for fast access of symbols based on name. // Symbol lookup based on name and indexed by version.
HashName map[string]*LSym Hash []map[string]*LSym
// Fallback map based also on version, for symbols
// with more than one version (see func _lookup).
HashVersion map[symVer]*LSym
Allsym []*LSym Allsym []*LSym
Tlsg *LSym Tlsg *LSym
...@@ -212,6 +209,11 @@ func (ctxt *Link) FixedFrameSize() int64 { ...@@ -212,6 +209,11 @@ func (ctxt *Link) FixedFrameSize() int64 {
} }
} }
func (l *Link) IncVersion() {
l.Version++
l.Hash = append(l.Hash, make(map[string]*LSym))
}
type LinkArch struct { type LinkArch struct {
ByteOrder binary.ByteOrder ByteOrder binary.ByteOrder
Name string Name string
......
...@@ -116,7 +116,7 @@ const ( ...@@ -116,7 +116,7 @@ const (
func ldobjfile(ctxt *Link, f *obj.Biobuf, pkg string, length int64, pn string) { func ldobjfile(ctxt *Link, f *obj.Biobuf, pkg string, length int64, pn string) {
start := obj.Boffset(f) start := obj.Boffset(f)
ctxt.Version++ ctxt.IncVersion()
var buf [8]uint8 var buf [8]uint8
obj.Bread(f, buf[:]) obj.Bread(f, buf[:])
if string(buf[:]) != startmagic { if string(buf[:]) != startmagic {
......
...@@ -58,12 +58,14 @@ var headers = []struct { ...@@ -58,12 +58,14 @@ var headers = []struct {
func linknew(arch *LinkArch) *Link { func linknew(arch *LinkArch) *Link {
ctxt := &Link{ ctxt := &Link{
HashName: make(map[string]*LSym, 100000), // preallocate about 2mb for hash Hash: []map[string]*LSym{
HashVersion: make(map[symVer]*LSym), // preallocate about 2mb for hash of
Allsym: make([]*LSym, 0, 100000), // non static symbols
Arch: arch, make(map[string]*LSym, 100000),
Version: obj.HistVersion, },
Goroot: obj.Getgoroot(), Allsym: make([]*LSym, 0, 100000),
Arch: arch,
Goroot: obj.Getgoroot(),
} }
p := obj.Getgoarch() p := obj.Getgoarch()
...@@ -158,7 +160,7 @@ func linknew(arch *LinkArch) *Link { ...@@ -158,7 +160,7 @@ func linknew(arch *LinkArch) *Link {
return ctxt return ctxt
} }
func linknewsym(ctxt *Link, symb string, v int) *LSym { func linknewsym(ctxt *Link, name string, v int) *LSym {
batch := ctxt.LSymBatch batch := ctxt.LSymBatch
if len(batch) == 0 { if len(batch) == 0 {
batch = make([]LSym, 1000) batch = make([]LSym, 1000)
...@@ -169,55 +171,28 @@ func linknewsym(ctxt *Link, symb string, v int) *LSym { ...@@ -169,55 +171,28 @@ func linknewsym(ctxt *Link, symb string, v int) *LSym {
s.Dynid = -1 s.Dynid = -1
s.Plt = -1 s.Plt = -1
s.Got = -1 s.Got = -1
s.Name = symb s.Name = name
s.Version = int16(v) s.Version = int16(v)
ctxt.Allsym = append(ctxt.Allsym, s) ctxt.Allsym = append(ctxt.Allsym, s)
return s return s
} }
type symVer struct { func Linklookup(ctxt *Link, name string, v int) *LSym {
sym string m := ctxt.Hash[v]
ver int s := m[name]
}
func _lookup(ctxt *Link, symb string, v int, creat int) *LSym {
// Most symbols have only a single version, and a string key
// is faster to search for. So we store the first symbol in HashName,
// keyed only by symbol name. If there are name collisions, the
// alternate versions are stored in the spill over map
// HashVersion.
s, exist := ctxt.HashName[symb]
if s != nil { if s != nil {
if int(s.Version) == v { return s
return s
}
s = ctxt.HashVersion[symVer{symb, v}]
if s != nil {
return s
}
}
if creat == 0 {
return nil
} }
s = linknewsym(ctxt, name, v)
s = linknewsym(ctxt, symb, v)
s.Extname = s.Name s.Extname = s.Name
if exist { m[name] = s
ctxt.HashVersion[symVer{symb, v}] = s
} else {
ctxt.HashName[symb] = s
}
return s return s
} }
func Linklookup(ctxt *Link, name string, v int) *LSym {
return _lookup(ctxt, name, v, 1)
}
// read-only lookup // read-only lookup
func Linkrlookup(ctxt *Link, name string, v int) *LSym { func Linkrlookup(ctxt *Link, name string, v int) *LSym {
return _lookup(ctxt, name, v, 0) return ctxt.Hash[v][name]
} }
func Headstr(v int) string { func Headstr(v int) string {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment