From 8e100a05a5d72c2f2b079d8791edf700c612e45e Mon Sep 17 00:00:00 2001 From: Cherry Zhang Date: Wed, 11 Mar 2020 17:00:08 -0400 Subject: [PATCH] [dev.link] cmd/internal/goobj2, cmd/link: avoid some repeated offset calculations MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit When iterating relocations, do the offset calculation just once. This gives some speedup: (linking cmd/compile) Deadcode 52.8ms ± 1% 47.6ms ± 1% -10.01% (p=0.008 n=5+5) Dostkcheck 44.2ms ± 1% 41.0ms ± 1% -7.29% (p=0.008 n=5+5) Change-Id: I09e38bc29afc379a81f99e3ee4ff467bc1b5f8a5 Reviewed-on: https://go-review.googlesource.com/c/go/+/222302 Reviewed-by: Than McIntosh --- src/cmd/internal/goobj2/objfile.go | 7 +++++++ src/cmd/link/internal/ld/deadcode2.go | 6 ++++-- src/cmd/link/internal/loader/loader.go | 13 ++++++++++--- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/cmd/internal/goobj2/objfile.go b/src/cmd/internal/goobj2/objfile.go index d93c28afff..ca254b28e0 100644 --- a/src/cmd/internal/goobj2/objfile.go +++ b/src/cmd/internal/goobj2/objfile.go @@ -595,6 +595,13 @@ func (r *Reader) Reloc2(i int, j int) *Reloc2 { return (*Reloc2)(unsafe.Pointer(&r.b[off])) } +// Relocs2 returns a pointer to the relocations of the i-th symbol. +func (r *Reader) Relocs2(i int) []Reloc2 { + off := r.RelocOff(i, 0) + n := r.NReloc(i) + return (*[1 << 20]Reloc2)(unsafe.Pointer(&r.b[off]))[:n:n] +} + // NAux returns the number of aux symbols of the i-th symbol. func (r *Reader) NAux(i int) int { auxIdxOff := r.h.Offsets[BlkAuxIdx] + uint32(i*4) diff --git a/src/cmd/link/internal/ld/deadcode2.go b/src/cmd/link/internal/ld/deadcode2.go index a7a41e3e16..cbf7e22dbd 100644 --- a/src/cmd/link/internal/ld/deadcode2.go +++ b/src/cmd/link/internal/ld/deadcode2.go @@ -172,8 +172,10 @@ func (d *deadcodePass2) flood() { // so we make sure we're pulling in all outer symbols, and their sub // symbols. This is not ideal, and these carrier/section symbols could // be removed. - d.mark(d.ldr.OuterSym(symIdx), symIdx) - d.mark(d.ldr.SubSym(symIdx), symIdx) + if d.ldr.IsExternal(symIdx) { + d.mark(d.ldr.OuterSym(symIdx), symIdx) + d.mark(d.ldr.SubSym(symIdx), symIdx) + } if len(methods) != 0 { if !isgotype { diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go index 95d2ac8a7f..93cfd44b8f 100644 --- a/src/cmd/link/internal/loader/loader.go +++ b/src/cmd/link/internal/loader/loader.go @@ -31,7 +31,9 @@ type Sym int // Relocs encapsulates the set of relocations on a given symbol; an // instance of this type is returned by the Loader Relocs() method. type Relocs struct { - Count int // number of relocs + Count int // == len(rs), TODO: remove + + rs []goobj2.Reloc2 li int // local index of symbol whose relocs we're examining r *oReader // object reader for containing package @@ -1469,11 +1471,13 @@ func (relocs *Relocs) At2(j int) Reloc2 { // XXX populate a goobj2.Reloc from external reloc record. // Ugly. Maybe we just want to use this format to store the // reloc record in the first place? + // Also there is more speedup if we could remove the + // conditional here. var b goobj2.Reloc2 b.Set(r.Off, r.Size, 0, r.Add, goobj2.SymRef{PkgIdx: 0, SymIdx: uint32(r.Sym)}) return Reloc2{&b, relocs.r, relocs.l, r.Type} } - return Reloc2{relocs.r.Reloc2(relocs.li, j), relocs.r, relocs.l, 0} + return Reloc2{&relocs.rs[j], relocs.r, relocs.l, 0} } // ReadAll method reads all relocations for a symbol into the @@ -1539,14 +1543,17 @@ func (l *Loader) Relocs(i Sym) Relocs { // Relocs returns a Relocs object given a local sym index and reader. func (l *Loader) relocs(r *oReader, li int) Relocs { var n int + var rs []goobj2.Reloc2 if l.isExtReader(r) { pp := l.payloads[li] n = len(pp.relocs) } else { - n = r.NReloc(li) + rs = r.Relocs2(li) + n = len(rs) } return Relocs{ Count: n, + rs: rs, li: li, r: r, l: l, -- 2.50.0