Skip to content

Commit

Permalink
[dev.link] cmd/link: use function address directly in pclntab generation
Browse files Browse the repository at this point in the history
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 <[email protected]>
TryBot-Result: Gobot Gobot <[email protected]>
Reviewed-by: Than McIntosh <[email protected]>
  • Loading branch information
cherrymui committed Apr 20, 2020
1 parent 93c9a3b commit c364079
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 8 deletions.
28 changes: 20 additions & 8 deletions src/cmd/link/internal/ld/pcln.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{}
Expand All @@ -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++
}
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -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)
}
Expand All @@ -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())
Expand Down
4 changes: 4 additions & 0 deletions src/cmd/link/internal/ld/target.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down

0 comments on commit c364079

Please sign in to comment.