mirror of https://github.com/golang/go.git
[dev.link] cmd/link: use new relocation accessors in DWARF generation
This gives some speedup and reduces some allocations: (linking cmd/compile) DwarfGenerateDebugInfo 63.2ms ± 3% 41.7ms ± 3% -34.04% (p=0.008 n=5+5) DwarfGenerateDebugInfo 20.0MB ± 0% 10.1MB ± 0% -49.62% (p=0.008 n=5+5) There are code that modify relocations, which are still using the earlier loader.Reloc slice for now. Change-Id: I3359ba305bf82cc882ae3c0f548d6ccfc8add789 Reviewed-on: https://go-review.googlesource.com/c/go/+/223663 Run-TryBot: Cherry Zhang <cherryyz@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Than McIntosh <thanm@google.com>
This commit is contained in:
parent
8a074fa275
commit
61a0b0d624
|
|
@ -306,8 +306,8 @@ func (d *deadcodePass2) decodeMethodSig2(ldr *loader.Loader, arch *sys.Arch, sym
|
|||
var buf bytes.Buffer
|
||||
var methods []methodsig
|
||||
for i := 0; i < count; i++ {
|
||||
buf.WriteString(decodetypeName3(ldr, symIdx, relocs, off))
|
||||
mtypSym := decodeRelocSym3(ldr, symIdx, relocs, int32(off+4))
|
||||
buf.WriteString(decodetypeName2(ldr, symIdx, relocs, off))
|
||||
mtypSym := decodeRelocSym2(ldr, symIdx, relocs, int32(off+4))
|
||||
// FIXME: add some sort of caching here, since we may see some of the
|
||||
// same symbols over time for param types.
|
||||
mrelocs := ldr.Relocs(mtypSym)
|
||||
|
|
@ -319,7 +319,7 @@ func (d *deadcodePass2) decodeMethodSig2(ldr *loader.Loader, arch *sys.Arch, sym
|
|||
if i > 0 {
|
||||
buf.WriteString(", ")
|
||||
}
|
||||
a := decodetypeFuncInType3(ldr, arch, mtypSym, &mrelocs, i)
|
||||
a := decodetypeFuncInType2(ldr, arch, mtypSym, &mrelocs, i)
|
||||
buf.WriteString(ldr.SymName(a))
|
||||
}
|
||||
buf.WriteString(") (")
|
||||
|
|
@ -328,7 +328,7 @@ func (d *deadcodePass2) decodeMethodSig2(ldr *loader.Loader, arch *sys.Arch, sym
|
|||
if i > 0 {
|
||||
buf.WriteString(", ")
|
||||
}
|
||||
a := decodetypeFuncOutType3(ldr, arch, mtypSym, &mrelocs, i)
|
||||
a := decodetypeFuncOutType2(ldr, arch, mtypSym, &mrelocs, i)
|
||||
buf.WriteString(ldr.SymName(a))
|
||||
}
|
||||
buf.WriteRune(')')
|
||||
|
|
@ -345,7 +345,7 @@ func (d *deadcodePass2) decodeIfaceMethods2(ldr *loader.Loader, arch *sys.Arch,
|
|||
if decodetypeKind(arch, p)&kindMask != kindInterface {
|
||||
panic(fmt.Sprintf("symbol %q is not an interface", ldr.SymName(symIdx)))
|
||||
}
|
||||
rel := decodeReloc3(ldr, symIdx, relocs, int32(commonsize(arch)+arch.PtrSize))
|
||||
rel := decodeReloc2(ldr, symIdx, relocs, int32(commonsize(arch)+arch.PtrSize))
|
||||
s := rel.Sym()
|
||||
if s == 0 {
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -15,17 +15,7 @@ import (
|
|||
// At some point we'll want to migrate the contents of this file
|
||||
// to decodesym.go once the rouetines there have been decprecated + removed.
|
||||
|
||||
func decodeReloc2(ldr *loader.Loader, symIdx loader.Sym, symRelocs []loader.Reloc, off int32) loader.Reloc {
|
||||
for j := 0; j < len(symRelocs); j++ {
|
||||
rel := symRelocs[j]
|
||||
if rel.Off == off {
|
||||
return rel
|
||||
}
|
||||
}
|
||||
return loader.Reloc{}
|
||||
}
|
||||
|
||||
func decodeReloc3(ldr *loader.Loader, symIdx loader.Sym, relocs *loader.Relocs, off int32) loader.Reloc2 {
|
||||
func decodeReloc2(ldr *loader.Loader, symIdx loader.Sym, relocs *loader.Relocs, off int32) loader.Reloc2 {
|
||||
for j := 0; j < relocs.Count; j++ {
|
||||
rel := relocs.At2(j)
|
||||
if rel.Off() == off {
|
||||
|
|
@ -35,17 +25,13 @@ func decodeReloc3(ldr *loader.Loader, symIdx loader.Sym, relocs *loader.Relocs,
|
|||
return loader.Reloc2{}
|
||||
}
|
||||
|
||||
func decodeRelocSym2(ldr *loader.Loader, symIdx loader.Sym, symRelocs []loader.Reloc, off int32) loader.Sym {
|
||||
return decodeReloc2(ldr, symIdx, symRelocs, off).Sym
|
||||
}
|
||||
|
||||
func decodeRelocSym3(ldr *loader.Loader, symIdx loader.Sym, relocs *loader.Relocs, off int32) loader.Sym {
|
||||
return decodeReloc3(ldr, symIdx, relocs, off).Sym()
|
||||
func decodeRelocSym2(ldr *loader.Loader, symIdx loader.Sym, relocs *loader.Relocs, off int32) loader.Sym {
|
||||
return decodeReloc2(ldr, symIdx, relocs, off).Sym()
|
||||
}
|
||||
|
||||
// decodetypeName2 decodes the name from a reflect.name.
|
||||
func decodetypeName2(ldr *loader.Loader, symIdx loader.Sym, symRelocs []loader.Reloc, off int) string {
|
||||
r := decodeRelocSym2(ldr, symIdx, symRelocs, int32(off))
|
||||
func decodetypeName2(ldr *loader.Loader, symIdx loader.Sym, relocs *loader.Relocs, off int) string {
|
||||
r := decodeRelocSym2(ldr, symIdx, relocs, int32(off))
|
||||
if r == 0 {
|
||||
return ""
|
||||
}
|
||||
|
|
@ -55,18 +41,7 @@ func decodetypeName2(ldr *loader.Loader, symIdx loader.Sym, symRelocs []loader.R
|
|||
return string(data[3 : 3+namelen])
|
||||
}
|
||||
|
||||
func decodetypeName3(ldr *loader.Loader, symIdx loader.Sym, relocs *loader.Relocs, off int) string {
|
||||
r := decodeRelocSym3(ldr, symIdx, relocs, int32(off))
|
||||
if r == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
data := ldr.Data(r)
|
||||
namelen := int(uint16(data[1])<<8 | uint16(data[2]))
|
||||
return string(data[3 : 3+namelen])
|
||||
}
|
||||
|
||||
func decodetypeFuncInType2(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, symRelocs []loader.Reloc, i int) loader.Sym {
|
||||
func decodetypeFuncInType2(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, relocs *loader.Relocs, i int) loader.Sym {
|
||||
uadd := commonsize(arch) + 4
|
||||
if arch.PtrSize == 8 {
|
||||
uadd += 4
|
||||
|
|
@ -74,35 +49,16 @@ func decodetypeFuncInType2(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym
|
|||
if decodetypeHasUncommon(arch, ldr.Data(symIdx)) {
|
||||
uadd += uncommonSize()
|
||||
}
|
||||
return decodeRelocSym2(ldr, symIdx, symRelocs, int32(uadd+i*arch.PtrSize))
|
||||
return decodeRelocSym2(ldr, symIdx, relocs, int32(uadd+i*arch.PtrSize))
|
||||
}
|
||||
|
||||
func decodetypeFuncInType3(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, relocs *loader.Relocs, i int) loader.Sym {
|
||||
uadd := commonsize(arch) + 4
|
||||
if arch.PtrSize == 8 {
|
||||
uadd += 4
|
||||
}
|
||||
if decodetypeHasUncommon(arch, ldr.Data(symIdx)) {
|
||||
uadd += uncommonSize()
|
||||
}
|
||||
return decodeRelocSym3(ldr, symIdx, relocs, int32(uadd+i*arch.PtrSize))
|
||||
}
|
||||
|
||||
func decodetypeFuncOutType2(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, symRelocs []loader.Reloc, i int) loader.Sym {
|
||||
return decodetypeFuncInType2(ldr, arch, symIdx, symRelocs, i+decodetypeFuncInCount(arch, ldr.Data(symIdx)))
|
||||
}
|
||||
|
||||
func decodetypeFuncOutType3(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, relocs *loader.Relocs, i int) loader.Sym {
|
||||
return decodetypeFuncInType3(ldr, arch, symIdx, relocs, i+decodetypeFuncInCount(arch, ldr.Data(symIdx)))
|
||||
func decodetypeFuncOutType2(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, relocs *loader.Relocs, i int) loader.Sym {
|
||||
return decodetypeFuncInType2(ldr, arch, symIdx, relocs, i+decodetypeFuncInCount(arch, ldr.Data(symIdx)))
|
||||
}
|
||||
|
||||
func decodetypeArrayElem2(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) loader.Sym {
|
||||
// FIXME: it's inefficient to read the relocations each time. Add some
|
||||
// sort of cache here, or pass in the relocs. Alternatively we could
|
||||
// switch to relocs.At() to see if that performs better.
|
||||
relocs := ldr.Relocs(symIdx)
|
||||
rslice := relocs.ReadAll(nil)
|
||||
return decodeRelocSym2(ldr, symIdx, rslice, int32(commonsize(arch))) // 0x1c / 0x30
|
||||
return decodeRelocSym2(ldr, symIdx, &relocs, int32(commonsize(arch))) // 0x1c / 0x30
|
||||
}
|
||||
|
||||
func decodetypeArrayLen2(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) int64 {
|
||||
|
|
@ -111,38 +67,23 @@ func decodetypeArrayLen2(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym)
|
|||
}
|
||||
|
||||
func decodetypeChanElem2(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) loader.Sym {
|
||||
// FIXME: it's inefficient to read the relocations each time. Add some
|
||||
// sort of cache here, or pass in the relocs.
|
||||
relocs := ldr.Relocs(symIdx)
|
||||
rslice := relocs.ReadAll(nil)
|
||||
return decodeRelocSym2(ldr, symIdx, rslice, int32(commonsize(arch))) // 0x1c / 0x30
|
||||
return decodeRelocSym2(ldr, symIdx, &relocs, int32(commonsize(arch))) // 0x1c / 0x30
|
||||
}
|
||||
|
||||
func decodetypeMapKey2(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) loader.Sym {
|
||||
// FIXME: it's inefficient to read the relocations each time. Add some
|
||||
// sort of cache here, or pass in the relocs. Alternatively we could
|
||||
// switch to relocs.At() to see if that performs better.
|
||||
relocs := ldr.Relocs(symIdx)
|
||||
rslice := relocs.ReadAll(nil)
|
||||
return decodeRelocSym2(ldr, symIdx, rslice, int32(commonsize(arch))) // 0x1c / 0x30
|
||||
return decodeRelocSym2(ldr, symIdx, &relocs, int32(commonsize(arch))) // 0x1c / 0x30
|
||||
}
|
||||
|
||||
func decodetypeMapValue2(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) loader.Sym {
|
||||
// FIXME: it's inefficient to read the relocations each time. Add some
|
||||
// sort of cache here, or pass in the relocs. Alternatively we could
|
||||
// switch to relocs.At() to see if that performs better.
|
||||
relocs := ldr.Relocs(symIdx)
|
||||
rslice := relocs.ReadAll(nil)
|
||||
return decodeRelocSym2(ldr, symIdx, rslice, int32(commonsize(arch))+int32(arch.PtrSize)) // 0x20 / 0x38
|
||||
return decodeRelocSym2(ldr, symIdx, &relocs, int32(commonsize(arch))+int32(arch.PtrSize)) // 0x20 / 0x38
|
||||
}
|
||||
|
||||
func decodetypePtrElem2(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) loader.Sym {
|
||||
// FIXME: it's inefficient to read the relocations each time. Add some
|
||||
// sort of cache here, or pass in the relocs. Alternatively we could
|
||||
// switch to relocs.At() to see if that performs better.
|
||||
relocs := ldr.Relocs(symIdx)
|
||||
rslice := relocs.ReadAll(nil)
|
||||
return decodeRelocSym2(ldr, symIdx, rslice, int32(commonsize(arch))) // 0x1c / 0x30
|
||||
return decodeRelocSym2(ldr, symIdx, &relocs, int32(commonsize(arch))) // 0x1c / 0x30
|
||||
}
|
||||
|
||||
func decodetypeStructFieldCount2(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) int {
|
||||
|
|
@ -162,22 +103,14 @@ func decodetypeStructFieldArrayOff2(ldr *loader.Loader, arch *sys.Arch, symIdx l
|
|||
|
||||
func decodetypeStructFieldName2(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, i int) string {
|
||||
off := decodetypeStructFieldArrayOff2(ldr, arch, symIdx, i)
|
||||
// FIXME: it's inefficient to read the relocations each time. Add some
|
||||
// sort of cache here, or pass in the relocs. Alternatively we could
|
||||
// switch to relocs.At() to see if that performs better.
|
||||
relocs := ldr.Relocs(symIdx)
|
||||
rslice := relocs.ReadAll(nil)
|
||||
return decodetypeName2(ldr, symIdx, rslice, off)
|
||||
return decodetypeName2(ldr, symIdx, &relocs, off)
|
||||
}
|
||||
|
||||
func decodetypeStructFieldType2(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, i int) loader.Sym {
|
||||
off := decodetypeStructFieldArrayOff2(ldr, arch, symIdx, i)
|
||||
// FIXME: it's inefficient to read the relocations each time. Add some
|
||||
// sort of cache here, or pass in the relocs. Alternatively we could
|
||||
// switch to relocs.At() to see if that performs better.
|
||||
relocs := ldr.Relocs(symIdx)
|
||||
rslice := relocs.ReadAll(nil)
|
||||
return decodeRelocSym2(ldr, symIdx, rslice, int32(off+arch.PtrSize))
|
||||
return decodeRelocSym2(ldr, symIdx, &relocs, int32(off+arch.PtrSize))
|
||||
}
|
||||
|
||||
func decodetypeStructFieldOffsAnon2(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, i int) int64 {
|
||||
|
|
|
|||
|
|
@ -580,10 +580,9 @@ func (d *dwctxt2) newtype(gotype loader.Sym) *dwarf.DWDie {
|
|||
data := d.ldr.Data(gotype)
|
||||
// FIXME: add caching or reuse reloc slice.
|
||||
relocs := d.ldr.Relocs(gotype)
|
||||
rslice := relocs.ReadAll(nil)
|
||||
nfields := decodetypeFuncInCount(d.arch, data)
|
||||
for i := 0; i < nfields; i++ {
|
||||
s := decodetypeFuncInType2(d.ldr, d.arch, gotype, rslice, i)
|
||||
s := decodetypeFuncInType2(d.ldr, d.arch, gotype, &relocs, i)
|
||||
sn := d.ldr.SymName(s)
|
||||
fld := d.newdie(die, dwarf.DW_ABRV_FUNCTYPEPARAM, sn[5:], 0)
|
||||
d.newrefattr(fld, dwarf.DW_AT_type, d.defgotype(s))
|
||||
|
|
@ -594,7 +593,7 @@ func (d *dwctxt2) newtype(gotype loader.Sym) *dwarf.DWDie {
|
|||
}
|
||||
nfields = decodetypeFuncOutCount(d.arch, data)
|
||||
for i := 0; i < nfields; i++ {
|
||||
s := decodetypeFuncOutType2(d.ldr, d.arch, gotype, rslice, i)
|
||||
s := decodetypeFuncOutType2(d.ldr, d.arch, gotype, &relocs, i)
|
||||
sn := d.ldr.SymName(s)
|
||||
fld := d.newdie(die, dwarf.DW_ABRV_FUNCTYPEPARAM, sn[5:], 0)
|
||||
d.newrefattr(fld, dwarf.DW_AT_type, d.defptrto(d.defgotype(s)))
|
||||
|
|
@ -1109,22 +1108,22 @@ func (d *dwctxt2) importInfoSymbol(ctxt *Link, dsym loader.Sym) {
|
|||
if d.ldr.SymType(dsym) != sym.SDWARFINFO {
|
||||
log.Fatalf("error: DWARF info sym %d/%s with incorrect type %s", dsym, d.ldr.SymName(dsym), d.ldr.SymType(dsym).String())
|
||||
}
|
||||
drelocs := d.ldr.Relocs(dsym)
|
||||
rslice := drelocs.ReadSyms(nil)
|
||||
for i := 0; i < len(rslice); i++ {
|
||||
r := &rslice[i]
|
||||
if r.Type != objabi.R_DWARFSECREF {
|
||||
relocs := d.ldr.Relocs(dsym)
|
||||
for i := 0; i < relocs.Count; i++ {
|
||||
r := relocs.At2(i)
|
||||
if r.Type() != objabi.R_DWARFSECREF {
|
||||
continue
|
||||
}
|
||||
rsym := r.Sym()
|
||||
// If there is an entry for the symbol in our rtmap, then it
|
||||
// means we've processed the type already, and can skip this one.
|
||||
if _, ok := d.rtmap[r.Sym]; ok {
|
||||
if _, ok := d.rtmap[rsym]; ok {
|
||||
// type already generated
|
||||
continue
|
||||
}
|
||||
// FIXME: is there a way we could avoid materializing the
|
||||
// symbol name here?
|
||||
sn := d.ldr.SymName(r.Sym)
|
||||
sn := d.ldr.SymName(rsym)
|
||||
tn := sn[len(dwarf.InfoPrefix):]
|
||||
ts := d.ldr.Lookup("type."+tn, 0)
|
||||
d.defgotype(ts)
|
||||
|
|
@ -1848,7 +1847,6 @@ func dwarfGenerateDebugInfo(ctxt *Link) {
|
|||
// fake root DIE for compile unit DIEs
|
||||
var dwroot dwarf.DWDie
|
||||
flagVariants := make(map[string]bool)
|
||||
var relocs []loader.Reloc
|
||||
|
||||
for _, lib := range ctxt.Library {
|
||||
|
||||
|
|
@ -1929,11 +1927,10 @@ func dwarfGenerateDebugInfo(ctxt *Link) {
|
|||
}
|
||||
|
||||
drelocs := d.ldr.Relocs(infosym)
|
||||
relocs = drelocs.ReadSyms(relocs)
|
||||
for ri := 0; ri < drelocs.Count; ri++ {
|
||||
r := &relocs[ri]
|
||||
if r.Type == objabi.R_DWARFSECREF {
|
||||
rsym := r.Sym
|
||||
r := drelocs.At2(ri)
|
||||
if r.Type() == objabi.R_DWARFSECREF {
|
||||
rsym := r.Sym()
|
||||
rsn := d.ldr.SymName(rsym)
|
||||
if len(rsn) == 0 {
|
||||
continue
|
||||
|
|
@ -2011,12 +2008,11 @@ func dwarfGenerateDebugInfo(ctxt *Link) {
|
|||
for _, list := range lists {
|
||||
for _, s := range list {
|
||||
symIdx := loader.Sym(s)
|
||||
srelocs := d.ldr.Relocs(symIdx)
|
||||
relocs = srelocs.ReadSyms(relocs)
|
||||
for i := 0; i < len(relocs); i++ {
|
||||
r := &relocs[i]
|
||||
if r.Type == objabi.R_USETYPE {
|
||||
d.defgotype(r.Sym)
|
||||
relocs := d.ldr.Relocs(symIdx)
|
||||
for i := 0; i < relocs.Count; i++ {
|
||||
r := relocs.At2(i)
|
||||
if r.Type() == objabi.R_USETYPE {
|
||||
d.defgotype(r.Sym())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2122,20 +2118,19 @@ func (d *dwctxt2) dwarfGenerateDebugSyms() {
|
|||
|
||||
func (d *dwctxt2) collectlocs(syms []loader.Sym, units []*sym.CompilationUnit) []loader.Sym {
|
||||
empty := true
|
||||
rslice := []loader.Reloc{}
|
||||
for _, u := range units {
|
||||
for _, fn := range u.FuncDIEs2 {
|
||||
relocs := d.ldr.Relocs(loader.Sym(fn))
|
||||
rslice := relocs.ReadSyms(rslice)
|
||||
for i := range rslice {
|
||||
reloc := &rslice[i]
|
||||
if reloc.Type != objabi.R_DWARFSECREF {
|
||||
for i := 0; i < relocs.Count; i++ {
|
||||
reloc := relocs.At2(i)
|
||||
if reloc.Type() != objabi.R_DWARFSECREF {
|
||||
continue
|
||||
}
|
||||
if d.ldr.SymType(reloc.Sym) == sym.SDWARFLOC {
|
||||
d.ldr.SetAttrReachable(reloc.Sym, true)
|
||||
d.ldr.SetAttrNotInSymbolTable(reloc.Sym, true)
|
||||
syms = append(syms, reloc.Sym)
|
||||
rsym := reloc.Sym()
|
||||
if d.ldr.SymType(rsym) == sym.SDWARFLOC {
|
||||
d.ldr.SetAttrReachable(rsym, true)
|
||||
d.ldr.SetAttrNotInSymbolTable(rsym, true)
|
||||
syms = append(syms, rsym)
|
||||
empty = false
|
||||
// One location list entry per function, but many relocations to it. Don't duplicate.
|
||||
break
|
||||
|
|
|
|||
Loading…
Reference in New Issue