]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.link] cmd/link: unescape relocs passed to Archreloc2
authorCherry Zhang <cherryyz@google.com>
Thu, 30 Apr 2020 03:53:33 +0000 (23:53 -0400)
committerCherry Zhang <cherryyz@google.com>
Thu, 30 Apr 2020 15:53:32 +0000 (15:53 +0000)
Archreloc2 is a function pointer. It will escape its pointer
arguments. In relocsym, as we pass &r and &rr to Archreloc2, it
causes them to escape, even if Archreloc2 is not actually called.

Instead, pass r by value. loader.Reloc2 is a small structure
which is intended to be passed by value.

For rr, as Archreloc2 will likely return true, we speculatively
add it to extRelocs slice and use that space to pass to
Archreloc2.

Linking cmd/compile,

name              old alloc/op   new alloc/op   delta
Dwarfcompress_GC     110MB ± 0%      24MB ± 0%   -78.34%  (p=0.008 n=5+5)
Reloc_GC            24.6MB ± 0%     0.0MB ± 0%  -100.00%  (p=0.029 n=4+4)

Linking cmd/compile using external linking

name              old alloc/op   new alloc/op   delta
Reloc_GC             152MB ± 0%      36MB ± 0%   -76.07%  (p=0.008 n=5+5)

Change-Id: I1415479e0c17ea9787f9a62453dce00ad9ea792f
Reviewed-on: https://go-review.googlesource.com/c/go/+/231077
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
src/cmd/link/internal/ld/data.go
src/cmd/link/internal/ld/lib.go
src/cmd/link/internal/x86/asm.go

index 07b7ebd5182714c4bacf5059b745884bee79c6d8..ae515a7d46c1af609acd438fa3833c5798869455 100644 (file)
@@ -253,9 +253,21 @@ func relocsym(target *Target, ldr *loader.Loader, err *ErrorReporter, syms *Arch
                        case 8:
                                o = int64(target.Arch.ByteOrder.Uint64(P[off:]))
                        }
-                       var out int64
-                       var ok bool
-                       out, needExtReloc, ok = thearch.Archreloc2(target, ldr, syms, &r, &rr, s, o)
+                       var rp *loader.ExtReloc
+                       if target.IsExternal() {
+                               // Don't pass &rr directly to Archreloc2, which will escape rr
+                               // even if this case is not taken. Instead, as Archreloc2 will
+                               // likely return true, we speculatively add rr to extRelocs
+                               // and use that space to pass to Archreloc2.
+                               extRelocs = append(extRelocs, rr)
+                               rp = &extRelocs[len(extRelocs)-1]
+                       }
+                       out, needExtReloc1, ok := thearch.Archreloc2(target, ldr, syms, r, rp, s, o)
+                       if target.IsExternal() && !needExtReloc1 {
+                               // Speculation failed. Undo the append.
+                               extRelocs = extRelocs[:len(extRelocs)-1]
+                       }
+                       needExtReloc = false // already appended
                        if ok {
                                o = out
                        } else {
index 3b76f3a236e132c6b074dda291bb5154a4e546b4..9a87cbef3395500c0c9382a635db486bc0ac6a56 100644 (file)
@@ -246,7 +246,7 @@ type Arch struct {
        // indicates a fatal error).
        Archreloc func(target *Target, syms *ArchSyms, rel *sym.Reloc, sym *sym.Symbol,
                offset int64) (relocatedOffset int64, success bool)
-       Archreloc2 func(*Target, *loader.Loader, *ArchSyms, *loader.Reloc2, *loader.ExtReloc, loader.Sym, int64) (int64, bool, bool)
+       Archreloc2 func(*Target, *loader.Loader, *ArchSyms, loader.Reloc2, *loader.ExtReloc, loader.Sym, int64) (int64, bool, bool)
        // Archrelocvariant is a second arch-specific hook used for
        // relocation processing; it handles relocations where r.Type is
        // insufficient to describe the relocation (r.Variant !=
index 0a0052a4f5810875f59c3c2967e76a913df088ed..53e5c71712af31852c63a8037008355a4f194b37 100644 (file)
@@ -435,7 +435,7 @@ func pereloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, secto
        return true
 }
 
-func archreloc2(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r *loader.Reloc2, rr *loader.ExtReloc, sym loader.Sym, val int64) (int64, bool, bool) {
+func archreloc2(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loader.Reloc2, rr *loader.ExtReloc, sym loader.Sym, val int64) (int64, bool, bool) {
        return val, false, false
 }