[dev.link] cmd/link: move findfunctab to a generated symbol
Basically removes all allocation from findfunctab:
Findfunctab_GC 172kB ± 0% 0kB ± 0% ~ (p=1.000 n=1+1)
Change-Id: I246f7d2751317886b658f7ef672fb30b3c519668
Reviewed-on: https://go-review.googlesource.com/c/go/+/239281
Run-TryBot: Jeremy Faller <jeremy@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Than McIntosh <thanm@google.com>
diff --git a/src/cmd/link/internal/ld/pcln.go b/src/cmd/link/internal/ld/pcln.go
index 81f1a2d..5bbfbb0 100644
--- a/src/cmd/link/internal/ld/pcln.go
+++ b/src/cmd/link/internal/ld/pcln.go
@@ -585,9 +585,6 @@
// a given text symbols is a container (outer sym).
func (ctxt *Link) findfunctab(container loader.Bitmap) {
ldr := ctxt.loader
- t := ldr.CreateSymForUpdate("runtime.findfunctab", 0)
- t.SetType(sym.SRODATA)
- ldr.SetAttrLocal(t.Sym(), true)
// find min and max address
min := ldr.SymValue(ctxt.Textp[0])
@@ -598,67 +595,74 @@
// that map to that subbucket.
n := int32((max - min + SUBBUCKETSIZE - 1) / SUBBUCKETSIZE)
- indexes := make([]int32, n)
- for i := int32(0); i < n; i++ {
- indexes[i] = NOIDX
- }
- idx := int32(0)
- for i, s := range ctxt.Textp {
- if !emitPcln(ctxt, s, container) {
- continue
- }
- p := ldr.SymValue(s)
- var e loader.Sym
- i++
- if i < len(ctxt.Textp) {
- e = ctxt.Textp[i]
- }
- for e != 0 && !emitPcln(ctxt, e, container) && i < len(ctxt.Textp) {
- e = ctxt.Textp[i]
- i++
- }
- q := max
- if e != 0 {
- q = ldr.SymValue(e)
- }
+ nbuckets := int32((max - min + BUCKETSIZE - 1) / BUCKETSIZE)
- //print("%d: [%lld %lld] %s\n", idx, p, q, s->name);
- for ; p < q; p += SUBBUCKETSIZE {
- i = int((p - min) / SUBBUCKETSIZE)
+ size := 4*int64(nbuckets) + int64(n)
+
+ writeFindFuncTab := func(_ *Link, s loader.Sym) {
+ t := ldr.MakeSymbolUpdater(s)
+
+ indexes := make([]int32, n)
+ for i := int32(0); i < n; i++ {
+ indexes[i] = NOIDX
+ }
+ idx := int32(0)
+ for i, s := range ctxt.Textp {
+ if !emitPcln(ctxt, s, container) {
+ continue
+ }
+ p := ldr.SymValue(s)
+ var e loader.Sym
+ i++
+ if i < len(ctxt.Textp) {
+ e = ctxt.Textp[i]
+ }
+ for e != 0 && !emitPcln(ctxt, e, container) && i < len(ctxt.Textp) {
+ e = ctxt.Textp[i]
+ i++
+ }
+ q := max
+ if e != 0 {
+ q = ldr.SymValue(e)
+ }
+
+ //print("%d: [%lld %lld] %s\n", idx, p, q, s->name);
+ for ; p < q; p += SUBBUCKETSIZE {
+ i = int((p - min) / SUBBUCKETSIZE)
+ if indexes[i] > idx {
+ indexes[i] = idx
+ }
+ }
+
+ i = int((q - 1 - min) / SUBBUCKETSIZE)
if indexes[i] > idx {
indexes[i] = idx
}
+ idx++
}
- i = int((q - 1 - min) / SUBBUCKETSIZE)
- if indexes[i] > idx {
- indexes[i] = idx
- }
- idx++
- }
-
- // allocate table
- nbuckets := int32((max - min + BUCKETSIZE - 1) / BUCKETSIZE)
-
- t.Grow(4*int64(nbuckets) + int64(n))
-
- // fill in table
- for i := int32(0); i < nbuckets; i++ {
- base := indexes[i*SUBBUCKETS]
- if base == NOIDX {
- Errorf(nil, "hole in findfunctab")
- }
- t.SetUint32(ctxt.Arch, int64(i)*(4+SUBBUCKETS), uint32(base))
- for j := int32(0); j < SUBBUCKETS && i*SUBBUCKETS+j < n; j++ {
- idx = indexes[i*SUBBUCKETS+j]
- if idx == NOIDX {
+ // fill in table
+ for i := int32(0); i < nbuckets; i++ {
+ base := indexes[i*SUBBUCKETS]
+ if base == NOIDX {
Errorf(nil, "hole in findfunctab")
}
- if idx-base >= 256 {
- Errorf(nil, "too many functions in a findfunc bucket! %d/%d %d %d", i, nbuckets, j, idx-base)
- }
+ t.SetUint32(ctxt.Arch, int64(i)*(4+SUBBUCKETS), uint32(base))
+ for j := int32(0); j < SUBBUCKETS && i*SUBBUCKETS+j < n; j++ {
+ idx = indexes[i*SUBBUCKETS+j]
+ if idx == NOIDX {
+ Errorf(nil, "hole in findfunctab")
+ }
+ if idx-base >= 256 {
+ Errorf(nil, "too many functions in a findfunc bucket! %d/%d %d %d", i, nbuckets, j, idx-base)
+ }
- t.SetUint8(ctxt.Arch, int64(i)*(4+SUBBUCKETS)+4+int64(j), uint8(idx-base))
+ t.SetUint8(ctxt.Arch, int64(i)*(4+SUBBUCKETS)+4+int64(j), uint8(idx-base))
+ }
}
}
+
+ s := ctxt.createGeneratorSymbol("runtime.findfunctab", 0, sym.SRODATA, size, writeFindFuncTab)
+ ldr.SetAttrReachable(s, true)
+ ldr.SetAttrLocal(s, true)
}