Skip to content

Commit 26407b2

Browse files
committed
[dev.link] cmd/{compile,link}: remove pcdata tables from pclntab_old
Move the pctables out of pclntab_old. Creates a new generator symbol, runtime.pctab, which holds all the deduplicated pctables. Also, tightens up some of the types in runtime. Darwin, cmd/compile statistics: alloc/op Pclntab_GC 26.4MB ± 0% 13.8MB ± 0% allocs/op Pclntab_GC 89.9k ± 0% 86.4k ± 0% liveB Pclntab_GC 25.5M ± 0% 24.2M ± 0% No significant change in binary size. Change-Id: I1560fd4421f8a210f8d4b508fbc54e1780e338f9 Reviewed-on: https://go-review.googlesource.com/c/go/+/248332 Run-TryBot: Jeremy Faller <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Cherry Zhang <[email protected]>
1 parent 5387cdc commit 26407b2

File tree

8 files changed

+136
-72
lines changed

8 files changed

+136
-72
lines changed

src/cmd/link/internal/ld/data.go

+2
Original file line numberDiff line numberDiff line change
@@ -1925,6 +1925,7 @@ func (state *dodataState) allocateDataSections(ctxt *Link) {
19251925
ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.funcnametab", 0), sect)
19261926
ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.cutab", 0), sect)
19271927
ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.filetab", 0), sect)
1928+
ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.pctab", 0), sect)
19281929
ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.pclntab_old", 0), sect)
19291930
ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.epclntab", 0), sect)
19301931
if ctxt.HeadType == objabi.Haix {
@@ -2511,6 +2512,7 @@ func (ctxt *Link) address() []*sym.Segment {
25112512
ctxt.defineInternal("runtime.funcnametab", sym.SRODATA)
25122513
ctxt.defineInternal("runtime.cutab", sym.SRODATA)
25132514
ctxt.defineInternal("runtime.filetab", sym.SRODATA)
2515+
ctxt.defineInternal("runtime.pctab", sym.SRODATA)
25142516
ctxt.defineInternal("runtime.pclntab_old", sym.SRODATA)
25152517
ctxt.xdefine("runtime.epclntab", sym.SRODATA, int64(pclntab.Vaddr+pclntab.Length))
25162518
ctxt.xdefine("runtime.noptrdata", sym.SNOPTRDATA, int64(noptr.Vaddr))

src/cmd/link/internal/ld/pcln.go

+95-48
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ type pclntab struct {
4343
findfunctab loader.Sym
4444
cutab loader.Sym
4545
filetab loader.Sym
46+
pctab loader.Sym
4647

4748
// The number of functions + number of TEXT sections - 1. This is such an
4849
// unexpected value because platforms that have more than one TEXT section
@@ -273,10 +274,11 @@ func (state *pclntab) generatePCHeader(ctxt *Link) {
273274
off = writeSymOffset(off, state.funcnametab)
274275
off = writeSymOffset(off, state.cutab)
275276
off = writeSymOffset(off, state.filetab)
277+
off = writeSymOffset(off, state.pctab)
276278
off = writeSymOffset(off, state.pclntab)
277279
}
278280

279-
size := int64(8 + 6*ctxt.Arch.PtrSize)
281+
size := int64(8 + 7*ctxt.Arch.PtrSize)
280282
state.pcheader = state.addGeneratedSym(ctxt, "runtime.pcheader", size, writeHeader)
281283
}
282284

@@ -463,6 +465,68 @@ func (state *pclntab) generateFilenameTabs(ctxt *Link, compUnits []*sym.Compilat
463465
return cuOffsets
464466
}
465467

468+
// generatePctab creates the runtime.pctab variable, holding all the
469+
// deduplicated pcdata.
470+
func (state *pclntab) generatePctab(ctxt *Link, container loader.Bitmap) {
471+
ldr := ctxt.loader
472+
473+
// Pctab offsets of 0 are considered invalid in the runtime. We respect
474+
// that by just padding a single byte at the beginning of runtime.pctab,
475+
// that way no real offsets can be zero.
476+
size := int64(1)
477+
478+
// Walk the functions, finding offset to store each pcdata.
479+
seen := make(map[loader.Sym]struct{})
480+
saveOffset := func(pcSym loader.Sym) {
481+
if _, ok := seen[pcSym]; !ok {
482+
datSize := ldr.SymSize(pcSym)
483+
if datSize != 0 {
484+
ldr.SetSymValue(pcSym, size)
485+
} else {
486+
// Invalid PC data, record as zero.
487+
ldr.SetSymValue(pcSym, 0)
488+
}
489+
size += datSize
490+
seen[pcSym] = struct{}{}
491+
}
492+
}
493+
for _, s := range ctxt.Textp {
494+
if !emitPcln(ctxt, s, container) {
495+
continue
496+
}
497+
fi := ldr.FuncInfo(s)
498+
if !fi.Valid() {
499+
continue
500+
}
501+
fi.Preload()
502+
503+
pcSyms := []loader.Sym{fi.Pcsp(), fi.Pcfile(), fi.Pcline()}
504+
for _, pcSym := range pcSyms {
505+
saveOffset(pcSym)
506+
}
507+
for _, pcSym := range fi.Pcdata() {
508+
saveOffset(pcSym)
509+
}
510+
if fi.NumInlTree() > 0 {
511+
saveOffset(fi.Pcinline())
512+
}
513+
}
514+
515+
// TODO: There is no reason we need a generator for this variable, and it
516+
// could be moved to a carrier symbol. However, carrier symbols containing
517+
// carrier symbols don't work yet (as of Aug 2020). Once this is fixed,
518+
// runtime.pctab could just be a carrier sym.
519+
writePctab := func(ctxt *Link, s loader.Sym) {
520+
ldr := ctxt.loader
521+
sb := ldr.MakeSymbolUpdater(s)
522+
for sym := range seen {
523+
sb.SetBytesAt(ldr.SymValue(sym), ldr.Data(sym))
524+
}
525+
}
526+
527+
state.pctab = state.addGeneratedSym(ctxt, "runtime.pctab", size, writePctab)
528+
}
529+
466530
// pclntab initializes the pclntab symbol with
467531
// runtime function and file name information.
468532

@@ -494,6 +558,9 @@ func (ctxt *Link) pclntab(container loader.Bitmap) *pclntab {
494558
// runtime.filetab
495559
// []null terminated filename strings
496560
//
561+
// runtime.pctab
562+
// []byte of deduplicated pc data.
563+
//
497564
// runtime.pclntab_old
498565
// function table, alternating PC and offset to func struct [each entry thearch.ptrsize bytes]
499566
// end PC [thearch.ptrsize bytes]
@@ -514,6 +581,7 @@ func (ctxt *Link) pclntab(container loader.Bitmap) *pclntab {
514581
state.generatePCHeader(ctxt)
515582
state.generateFuncnametab(ctxt, container)
516583
cuOffsets := state.generateFilenameTabs(ctxt, compUnits, container)
584+
state.generatePctab(ctxt, container)
517585

518586
funcdataBytes := int64(0)
519587
ldr.SetCarrierSym(state.pclntab, state.carrier)
@@ -525,21 +593,6 @@ func (ctxt *Link) pclntab(container loader.Bitmap) *pclntab {
525593

526594
ftab.Grow(int64(state.nfunc)*2*int64(ctxt.Arch.PtrSize) + int64(ctxt.Arch.PtrSize) + 4)
527595

528-
szHint := len(ctxt.Textp) * 2
529-
pctaboff := make(map[string]uint32, szHint)
530-
writepctab := func(off int32, p []byte) int32 {
531-
start, ok := pctaboff[string(p)]
532-
if !ok {
533-
if len(p) > 0 {
534-
start = uint32(len(ftab.Data()))
535-
ftab.AddBytes(p)
536-
}
537-
pctaboff[string(p)] = start
538-
}
539-
newoff := int32(ftab.SetUint32(ctxt.Arch, int64(off), start))
540-
return newoff
541-
}
542-
543596
setAddr := (*loader.SymbolBuilder).SetAddrPlus
544597
if ctxt.IsExe() && ctxt.IsInternal() {
545598
// Internal linking static executable. At this point the function
@@ -555,10 +608,6 @@ func (ctxt *Link) pclntab(container loader.Bitmap) *pclntab {
555608
}
556609
}
557610

558-
pcsp := sym.Pcdata{}
559-
pcfile := sym.Pcdata{}
560-
pcline := sym.Pcdata{}
561-
pcdata := []sym.Pcdata{}
562611
funcdata := []loader.Sym{}
563612
funcdataoff := []int64{}
564613

@@ -583,34 +632,26 @@ func (ctxt *Link) pclntab(container loader.Bitmap) *pclntab {
583632
}
584633
prevFunc = s
585634

586-
pcsp.P = pcsp.P[:0]
587-
pcline.P = pcline.P[:0]
588-
pcfile.P = pcfile.P[:0]
589-
pcdata = pcdata[:0]
635+
var numPCData int32
590636
funcdataoff = funcdataoff[:0]
591637
funcdata = funcdata[:0]
592638
fi := ldr.FuncInfo(s)
593639
if fi.Valid() {
594640
fi.Preload()
595-
for _, dataSym := range fi.Pcdata() {
596-
pcdata = append(pcdata, sym.Pcdata{P: ldr.Data(dataSym)})
597-
}
641+
numPCData = int32(len(fi.Pcdata()))
598642
nfd := fi.NumFuncdataoff()
599643
for i := uint32(0); i < nfd; i++ {
600644
funcdataoff = append(funcdataoff, fi.Funcdataoff(int(i)))
601645
}
602646
funcdata = fi.Funcdata(funcdata)
603647
}
604648

649+
writeInlPCData := false
605650
if fi.Valid() && fi.NumInlTree() > 0 {
606-
607-
if len(pcdata) <= objabi.PCDATA_InlTreeIndex {
608-
// Create inlining pcdata table.
609-
newpcdata := make([]sym.Pcdata, objabi.PCDATA_InlTreeIndex+1)
610-
copy(newpcdata, pcdata)
611-
pcdata = newpcdata
651+
writeInlPCData = true
652+
if numPCData <= objabi.PCDATA_InlTreeIndex {
653+
numPCData = objabi.PCDATA_InlTreeIndex + 1
612654
}
613-
614655
if len(funcdataoff) <= objabi.FUNCDATA_InlTree {
615656
// Create inline tree funcdata.
616657
newfuncdata := make([]loader.Sym, objabi.FUNCDATA_InlTree+1)
@@ -635,7 +676,7 @@ func (ctxt *Link) pclntab(container loader.Bitmap) *pclntab {
635676
// fixed size of struct, checked below
636677
off := funcstart
637678

638-
end := funcstart + int32(ctxt.Arch.PtrSize) + 3*4 + 6*4 + int32(len(pcdata))*4 + int32(len(funcdata))*int32(ctxt.Arch.PtrSize)
679+
end := funcstart + int32(ctxt.Arch.PtrSize) + 3*4 + 6*4 + numPCData*4 + int32(len(funcdata))*int32(ctxt.Arch.PtrSize)
639680
if len(funcdata) > 0 && (end&int32(ctxt.Arch.PtrSize-1) != 0) {
640681
end += 4
641682
}
@@ -664,23 +705,21 @@ func (ctxt *Link) pclntab(container loader.Bitmap) *pclntab {
664705
off = int32(ftab.SetUint32(ctxt.Arch, int64(off), deferreturn))
665706

666707
cu := ldr.SymUnit(s)
667-
if fi.Valid() {
668-
pcsp = sym.Pcdata{P: ldr.Data(fi.Pcsp())}
669-
pcfile = sym.Pcdata{P: ldr.Data(fi.Pcfile())}
670-
pcline = sym.Pcdata{P: ldr.Data(fi.Pcline())}
671-
}
672708

673709
if fi.Valid() && fi.NumInlTree() > 0 {
674710
its := oldState.genInlTreeSym(cu, fi, ctxt.Arch, state)
675711
funcdata[objabi.FUNCDATA_InlTree] = its
676-
pcdata[objabi.PCDATA_InlTreeIndex] = sym.Pcdata{P: ldr.Data(fi.Pcinline())}
677712
}
678713

679714
// pcdata
680-
off = writepctab(off, pcsp.P)
681-
off = writepctab(off, pcfile.P)
682-
off = writepctab(off, pcline.P)
683-
off = int32(ftab.SetUint32(ctxt.Arch, int64(off), uint32(len(pcdata))))
715+
if fi.Valid() {
716+
off = int32(ftab.SetUint32(ctxt.Arch, int64(off), uint32(ldr.SymValue(fi.Pcsp()))))
717+
off = int32(ftab.SetUint32(ctxt.Arch, int64(off), uint32(ldr.SymValue(fi.Pcfile()))))
718+
off = int32(ftab.SetUint32(ctxt.Arch, int64(off), uint32(ldr.SymValue(fi.Pcline()))))
719+
} else {
720+
off += 12
721+
}
722+
off = int32(ftab.SetUint32(ctxt.Arch, int64(off), uint32(numPCData)))
684723

685724
// Store the offset to compilation unit's file table.
686725
cuIdx := ^uint32(0)
@@ -700,9 +739,17 @@ func (ctxt *Link) pclntab(container loader.Bitmap) *pclntab {
700739

701740
// nfuncdata must be the final entry.
702741
off = int32(ftab.SetUint8(ctxt.Arch, int64(off), uint8(len(funcdata))))
703-
for i := range pcdata {
704-
off = writepctab(off, pcdata[i].P)
742+
743+
// Output the pcdata.
744+
if fi.Valid() {
745+
for i, pcSym := range fi.Pcdata() {
746+
ftab.SetUint32(ctxt.Arch, int64(off+int32(i*4)), uint32(ldr.SymValue(pcSym)))
747+
}
748+
if writeInlPCData {
749+
ftab.SetUint32(ctxt.Arch, int64(off+objabi.PCDATA_InlTreeIndex*4), uint32(ldr.SymValue(fi.Pcinline())))
750+
}
705751
}
752+
off += numPCData * 4
706753

707754
// funcdata, must be pointer-aligned and we're only int32-aligned.
708755
// Missing funcdata will be 0 (nil pointer).
@@ -724,7 +771,7 @@ func (ctxt *Link) pclntab(container loader.Bitmap) *pclntab {
724771
}
725772

726773
if off != end {
727-
ctxt.Errorf(s, "bad math in functab: funcstart=%d off=%d but end=%d (npcdata=%d nfuncdata=%d ptrsize=%d)", funcstart, off, end, len(pcdata), len(funcdata), ctxt.Arch.PtrSize)
774+
ctxt.Errorf(s, "bad math in functab: funcstart=%d off=%d but end=%d (npcdata=%d nfuncdata=%d ptrsize=%d)", funcstart, off, end, numPCData, len(funcdata), ctxt.Arch.PtrSize)
728775
errorexit()
729776
}
730777

src/cmd/link/internal/ld/symtab.go

+4
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,10 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind {
627627
moduledata.AddAddr(ctxt.Arch, pcln.filetab)
628628
moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(pcln.filetab)))
629629
moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(pcln.filetab)))
630+
// The pctab slice
631+
moduledata.AddAddr(ctxt.Arch, pcln.pctab)
632+
moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(pcln.pctab)))
633+
moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(pcln.pctab)))
630634
// The pclntab slice
631635
moduledata.AddAddr(ctxt.Arch, pcln.pclntab)
632636
moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(pcln.pclntab)))

src/cmd/link/internal/loader/symbolbuilder.go

+9
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,15 @@ func (sb *SymbolBuilder) Addstring(str string) int64 {
336336
return r
337337
}
338338

339+
func (sb *SymbolBuilder) SetBytesAt(off int64, b []byte) int64 {
340+
datLen := int64(len(b))
341+
if off+datLen > int64(len(sb.data)) {
342+
panic("attempt to write past end of buffer")
343+
}
344+
copy(sb.data[off:off+datLen], b)
345+
return off + datLen
346+
}
347+
339348
func (sb *SymbolBuilder) addSymRef(tgt Sym, add int64, typ objabi.RelocType, rsize int) int64 {
340349
if sb.kind == 0 {
341350
sb.kind = sym.SDATA

src/cmd/link/internal/sym/symbol.go

-4
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,3 @@ func VersionToABI(v int) (obj.ABI, bool) {
3333
}
3434
return ^obj.ABI(0), false
3535
}
36-
37-
type Pcdata struct {
38-
P []byte
39-
}

src/debug/gosym/pclntab.go

+7-3
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ type LineTable struct {
5858
functab []byte
5959
nfunctab uint32
6060
filetab []byte
61+
pctab []byte // points to the pctables.
6162
nfiletab uint32
6263
funcNames map[uint32]string // cache the function names
6364
strings map[uint32]string // interned substrings of Data, keyed by offset
@@ -235,6 +236,8 @@ func (t *LineTable) parsePclnTab() {
235236
offset = t.uintptr(t.Data[8+4*t.ptrsize:])
236237
t.filetab = t.Data[offset:]
237238
offset = t.uintptr(t.Data[8+5*t.ptrsize:])
239+
t.pctab = t.Data[offset:]
240+
offset = t.uintptr(t.Data[8+6*t.ptrsize:])
238241
t.funcdata = t.Data[offset:]
239242
t.functab = t.Data[offset:]
240243
functabsize := t.nfunctab*2*t.ptrsize + t.ptrsize
@@ -244,6 +247,7 @@ func (t *LineTable) parsePclnTab() {
244247
t.funcdata = t.Data
245248
t.funcnametab = t.Data
246249
t.functab = t.Data[8+t.ptrsize:]
250+
t.pctab = t.Data
247251
functabsize := t.nfunctab*2*t.ptrsize + t.ptrsize
248252
fileoff := t.binary.Uint32(t.functab[functabsize:])
249253
t.functab = t.functab[:functabsize]
@@ -373,7 +377,7 @@ func (t *LineTable) step(p *[]byte, pc *uint64, val *int32, first bool) bool {
373377
// off is the offset to the beginning of the pc-value table,
374378
// and entry is the start PC for the corresponding function.
375379
func (t *LineTable) pcvalue(off uint32, entry, targetpc uint64) int32 {
376-
p := t.funcdata[off:]
380+
p := t.pctab[off:]
377381

378382
val := int32(-1)
379383
pc := entry
@@ -396,8 +400,8 @@ func (t *LineTable) findFileLine(entry uint64, filetab, linetab uint32, filenum,
396400
return 0
397401
}
398402

399-
fp := t.funcdata[filetab:]
400-
fl := t.funcdata[linetab:]
403+
fp := t.pctab[filetab:]
404+
fl := t.pctab[linetab:]
401405
fileVal := int32(-1)
402406
filePC := entry
403407
lineVal := int32(-1)

src/runtime/runtime2.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -800,10 +800,10 @@ type _func struct {
800800
args int32 // in/out args size
801801
deferreturn uint32 // offset of start of a deferreturn call instruction from entry, if any.
802802

803-
pcsp int32
804-
pcfile int32
805-
pcln int32
806-
npcdata int32
803+
pcsp uint32
804+
pcfile uint32
805+
pcln uint32
806+
npcdata uint32
807807
cuOffset uint32 // runtime.cutab offset of this function's CU
808808
funcID funcID // set for certain special runtime functions
809809
_ [2]byte // pad

0 commit comments

Comments
 (0)