From c364079a533c172bd071af38b6f6ffd7dc68186d Mon Sep 17 00:00:00 2001 From: Cherry Zhang Date: Wed, 15 Apr 2020 22:23:41 -0400 Subject: [PATCH] [dev.link] cmd/link: use function address directly in pclntab generation MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit If we are internal linking a static executable, in pclntab generation, the function addresses are known, so we can just use them directly instead of emitting relocations. For external linking or other build modes, we are generating a relocatable binary so we still need to emit relocations. Reduce some allocations: for linking cmd/compile, name old alloc/op new alloc/op delta Pclntab_GC 38.8MB ± 0% 36.4MB ± 0% -6.19% (p=0.008 n=5+5) TODO: can we also do this in DWARF generation? Change-Id: I43920d930ab1da97c205871027e01844a07a5e60 Reviewed-on: https://go-review.googlesource.com/c/go/+/228478 Run-TryBot: Cherry Zhang TryBot-Result: Gobot Gobot Reviewed-by: Than McIntosh --- src/cmd/link/internal/ld/pcln.go | 28 ++++++++++++++++++++-------- src/cmd/link/internal/ld/target.go | 4 ++++ 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/cmd/link/internal/ld/pcln.go b/src/cmd/link/internal/ld/pcln.go index b275d20856..7d5a756a62 100644 --- a/src/cmd/link/internal/ld/pcln.go +++ b/src/cmd/link/internal/ld/pcln.go @@ -325,6 +325,21 @@ func (ctxt *Link) pclntab() loader.Bitmap { return newoff } + setAddr := (*loader.SymbolBuilder).SetAddrPlus + if ctxt.IsExe() && ctxt.IsInternal() { + // Internal linking static executable. At this point the function + // addresses are known, so we can just use them instead of emitting + // relocations. + // For other cases we are generating a relocatable binary so we + // still need to emit relocations. + setAddr = func(s *loader.SymbolBuilder, arch *sys.Arch, off int64, tgt loader.Sym, add int64) int64 { + if v := ldr.SymValue(tgt); v != 0 { + return s.SetUint(arch, off, uint64(v+add)) + } + return s.SetAddrPlus(arch, off, tgt, add) + } + } + pcsp := sym.Pcdata{} pcfile := sym.Pcdata{} pcline := sym.Pcdata{} @@ -347,7 +362,7 @@ func (ctxt *Link) pclntab() loader.Bitmap { // invalid funcoff value to mark the hole. See also // runtime/symtab.go:findfunc prevFuncSize := int64(ldr.SymSize(prevFunc)) - ftab.SetAddrPlus(ctxt.Arch, 8+int64(ctxt.Arch.PtrSize)+int64(nfunc)*2*int64(ctxt.Arch.PtrSize), prevFunc, prevFuncSize) + setAddr(ftab, ctxt.Arch, 8+int64(ctxt.Arch.PtrSize)+int64(nfunc)*2*int64(ctxt.Arch.PtrSize), prevFunc, prevFuncSize) ftab.SetUint(ctxt.Arch, 8+int64(ctxt.Arch.PtrSize)+int64(nfunc)*2*int64(ctxt.Arch.PtrSize)+int64(ctxt.Arch.PtrSize), ^uint64(0)) nfunc++ } @@ -397,10 +412,7 @@ func (ctxt *Link) pclntab() loader.Bitmap { funcstart := int32(dSize) funcstart += int32(-dSize) & (int32(ctxt.Arch.PtrSize) - 1) // align to ptrsize - // NB: for the static binary internal-link case, we could just - // emit the symbol value instead of creating a relocation here - // (might speed things up for that case). - ftab.SetAddrPlus(ctxt.Arch, 8+int64(ctxt.Arch.PtrSize)+int64(nfunc)*2*int64(ctxt.Arch.PtrSize), s, 0) + setAddr(ftab, ctxt.Arch, 8+int64(ctxt.Arch.PtrSize)+int64(nfunc)*2*int64(ctxt.Arch.PtrSize), s, 0) ftab.SetUint(ctxt.Arch, 8+int64(ctxt.Arch.PtrSize)+int64(nfunc)*2*int64(ctxt.Arch.PtrSize)+int64(ctxt.Arch.PtrSize), uint64(funcstart)) // Write runtime._func. Keep in sync with ../../../../runtime/runtime2.go:/_func @@ -416,7 +428,7 @@ func (ctxt *Link) pclntab() loader.Bitmap { ftab.Grow(int64(end)) // entry uintptr - off = int32(ftab.SetAddrPlus(ctxt.Arch, int64(off), s, 0)) + off = int32(setAddr(ftab, ctxt.Arch, int64(off), s, 0)) // name int32 sn := ldr.SymName(s) @@ -497,7 +509,7 @@ func (ctxt *Link) pclntab() loader.Bitmap { } // TODO: Dedup. funcdataBytes += int64(len(ldr.Data(funcdata[i]))) - ftab.SetAddrPlus(ctxt.Arch, dataoff, funcdata[i], funcdataoff[i]) + setAddr(ftab, ctxt.Arch, dataoff, funcdata[i], funcdataoff[i]) } off += int32(len(funcdata)) * int32(ctxt.Arch.PtrSize) } @@ -513,7 +525,7 @@ func (ctxt *Link) pclntab() loader.Bitmap { last := ctxt.Textp2[len(ctxt.Textp2)-1] pclntabLastFunc2 = last // Final entry of table is just end pc. - ftab.SetAddrPlus(ctxt.Arch, 8+int64(ctxt.Arch.PtrSize)+int64(nfunc)*2*int64(ctxt.Arch.PtrSize), last, ldr.SymSize(last)) + setAddr(ftab, ctxt.Arch, 8+int64(ctxt.Arch.PtrSize)+int64(nfunc)*2*int64(ctxt.Arch.PtrSize), last, ldr.SymSize(last)) // Start file table. dSize := len(ftab.Data()) diff --git a/src/cmd/link/internal/ld/target.go b/src/cmd/link/internal/ld/target.go index 09a67365d0..7aa2c1ccd0 100644 --- a/src/cmd/link/internal/ld/target.go +++ b/src/cmd/link/internal/ld/target.go @@ -28,6 +28,10 @@ type Target struct { // Target type functions // +func (t *Target) IsExe() bool { + return t.BuildMode == BuildModeExe +} + func (t *Target) IsShared() bool { return t.BuildMode == BuildModeShared } -- 2.48.1