From 61a0b0d62461a8697db9869cfaf39471228e7903 Mon Sep 17 00:00:00 2001 From: Cherry Zhang Date: Mon, 16 Mar 2020 12:09:52 -0400 Subject: [PATCH] [dev.link] cmd/link: use new relocation accessors in DWARF generation MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 TryBot-Result: Gobot Gobot Reviewed-by: Than McIntosh --- src/cmd/link/internal/ld/deadcode2.go | 10 +-- src/cmd/link/internal/ld/decodesym2.go | 99 +++++--------------------- src/cmd/link/internal/ld/dwarf.go | 55 +++++++------- 3 files changed, 46 insertions(+), 118 deletions(-) diff --git a/src/cmd/link/internal/ld/deadcode2.go b/src/cmd/link/internal/ld/deadcode2.go index 5088a6e1be..892f3f41e5 100644 --- a/src/cmd/link/internal/ld/deadcode2.go +++ b/src/cmd/link/internal/ld/deadcode2.go @@ -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 diff --git a/src/cmd/link/internal/ld/decodesym2.go b/src/cmd/link/internal/ld/decodesym2.go index e93cc91a9f..d496721122 100644 --- a/src/cmd/link/internal/ld/decodesym2.go +++ b/src/cmd/link/internal/ld/decodesym2.go @@ -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)) -} - -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))) + return decodeRelocSym2(ldr, symIdx, relocs, int32(uadd+i*arch.PtrSize)) } -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 { diff --git a/src/cmd/link/internal/ld/dwarf.go b/src/cmd/link/internal/ld/dwarf.go index dcc957655a..a9a1a1c41f 100644 --- a/src/cmd/link/internal/ld/dwarf.go +++ b/src/cmd/link/internal/ld/dwarf.go @@ -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 -- 2.50.0