objSyms []objSym // global index mapping to local index
- hashed64Syms map[uint64]symAndSize // short hashed (content-addressable) symbols, keyed by content hash
- hashedSyms map[goobj2.HashType]symAndSize // hashed (content-addressable) symbols, keyed by content hash
- symsByName [2]map[string]Sym // map symbol name to index, two maps are for ABI0 and ABIInternal
- extStaticSyms map[nameVer]Sym // externally defined static symbols, keyed by name
+ symsByName [2]map[string]Sym // map symbol name to index, two maps are for ABI0 and ABIInternal
+ extStaticSyms map[nameVer]Sym // externally defined static symbols, keyed by name
extReader *oReader // a dummy oReader, for external symbols
payloadBatch []extSymPayload
errorReporter *ErrorReporter
- npkgsyms int // number of package symbols, for accounting
+ npkgsyms int // number of package symbols, for accounting
+ nhashedsyms int // number of hashed symbols, for accounting
}
const (
objs: []objIdx{{}, {extReader, 0}}, // reserve index 0 for nil symbol, 1 for external symbols
objSyms: make([]objSym, 1, 100000), // reserve index 0 for nil symbol
extReader: extReader,
- hashed64Syms: make(map[uint64]symAndSize, 10000), // TODO: adjust preallocation sizes
- hashedSyms: make(map[goobj2.HashType]symAndSize, 20000), // TODO: adjust preallocation sizes
symsByName: [2]map[string]Sym{make(map[string]Sym, 80000), make(map[string]Sym, 50000)}, // preallocate ~2MB for ABI0 and ~1MB for ABI1 symbols
objByPkg: make(map[string]*oReader),
outer: make(map[Sym]Sym),
// Add a symbol from an object file, return the global index.
// If the symbol already exist, it returns the index of that symbol.
-func (l *Loader) addSym(name string, ver int, r *oReader, li uint32, kind int, osym *goobj2.Sym) Sym {
+func (st *loadState) addSym(name string, ver int, r *oReader, li uint32, kind int, osym *goobj2.Sym) Sym {
+ l := st.l
if l.extStart != 0 {
panic("addSym called after external symbol is created")
}
if kind == hashed64Def {
checkHash = func() (symAndSize, bool) {
h64 = r.Hash64(li - uint32(r.ndef))
- s, existed := l.hashed64Syms[h64]
+ s, existed := st.hashed64Syms[h64]
return s, existed
}
- addToHashMap = func(ss symAndSize) { l.hashed64Syms[h64] = ss }
+ addToHashMap = func(ss symAndSize) { st.hashed64Syms[h64] = ss }
} else {
checkHash = func() (symAndSize, bool) {
h = r.Hash(li - uint32(r.ndef+r.nhashed64def))
- s, existed := l.hashedSyms[*h]
+ s, existed := st.hashedSyms[*h]
return s, existed
}
- addToHashMap = func(ss symAndSize) { l.hashedSyms[*h] = ss }
+ addToHashMap = func(ss symAndSize) { st.hashedSyms[*h] = ss }
}
siz := osym.Siz()
if s, existed := checkHash(); existed {
}
l.addObj(lib.Pkg, or)
- l.preloadSyms(or, pkgDef)
+ st := loadState{l: l}
+ st.preloadSyms(or, pkgDef)
// The caller expects us consuming all the data
f.MustSeek(length, os.SEEK_CUR)
return r.Fingerprint()
}
+// Holds the loader along with temporary states for loading symbols.
+type loadState struct {
+ l *Loader
+ hashed64Syms map[uint64]symAndSize // short hashed (content-addressable) symbols, keyed by content hash
+ hashedSyms map[goobj2.HashType]symAndSize // hashed (content-addressable) symbols, keyed by content hash
+}
+
// Preload symbols of given kind from an object.
-func (l *Loader) preloadSyms(r *oReader, kind int) {
+func (st *loadState) preloadSyms(r *oReader, kind int) {
+ l := st.l
var start, end uint32
switch kind {
case pkgDef:
}
v = abiToVer(osym.ABI(), r.version)
}
- gi := l.addSym(name, v, r, i, kind, osym)
+ gi := st.addSym(name, v, r, i, kind, osym)
r.syms[i] = gi
if osym.TopFrame() {
l.SetAttrTopFrame(gi, true)
// references to external symbols (which are always named).
func (l *Loader) LoadNonpkgSyms(arch *sys.Arch) {
l.npkgsyms = l.NSym()
+ // Preallocate some space (a few hundreds KB) for some symbols.
+ // As of Go 1.15, linking cmd/compile has ~8000 hashed64 symbols and
+ // ~13000 hashed symbols.
+ st := loadState{
+ l: l,
+ hashed64Syms: make(map[uint64]symAndSize, 10000),
+ hashedSyms: make(map[goobj2.HashType]symAndSize, 15000),
+ }
for _, o := range l.objs[goObjStart:] {
- l.preloadSyms(o.r, hashed64Def)
- l.preloadSyms(o.r, hashedDef)
- l.preloadSyms(o.r, nonPkgDef)
+ st.preloadSyms(o.r, hashed64Def)
+ st.preloadSyms(o.r, hashedDef)
+ st.preloadSyms(o.r, nonPkgDef)
}
+ l.nhashedsyms = len(st.hashed64Syms) + len(st.hashedSyms)
for _, o := range l.objs[goObjStart:] {
loadObjRefs(l, o.r, arch)
}
func (l *Loader) Stat() string {
s := fmt.Sprintf("%d symbols, %d reachable\n", l.NSym(), l.NReachableSym())
s += fmt.Sprintf("\t%d package symbols, %d hashed symbols, %d non-package symbols, %d external symbols\n",
- l.npkgsyms, len(l.hashed64Syms)+len(l.hashedSyms), int(l.extStart)-l.npkgsyms-len(l.hashed64Syms)-len(l.hashedSyms), l.NSym()-int(l.extStart))
+ l.npkgsyms, l.nhashedsyms, int(l.extStart)-l.npkgsyms-l.nhashedsyms, l.NSym()-int(l.extStart))
return s
}