1
0
mirror of https://github.com/golang/go synced 2024-11-18 00:04:43 -07:00

[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>
This commit is contained in:
Jeremy Faller 2020-06-22 11:11:12 -04:00
parent f033e23414
commit 1fdf5ba50c

View File

@ -585,9 +585,6 @@ const (
// 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 @@ func (ctxt *Link) findfunctab(container loader.Bitmap) {
// 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)
}