diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go index 25dda36293..4b1975dcd9 100644 --- a/src/cmd/link/internal/ld/data.go +++ b/src/cmd/link/internal/ld/data.go @@ -127,6 +127,8 @@ func trampoline(ctxt *Link, s *sym.Symbol) { // // This is a performance-critical function for the linker; be careful // to avoid introducing unnecessary allocations in the main loop. +// TODO: This function is called in parallel. When the Loader wavefront +// reaches here, calls into the loader need to be parallel as well. func relocsym(target *Target, err *ErrorReporter, lookup LookupFn, syms *ArchSyms, s *sym.Symbol) { if len(s.R) == 0 { return @@ -2481,6 +2483,7 @@ func compressSyms(ctxt *Link, syms []*sym.Symbol) []byte { if len(s.R) != 0 && wasReadOnly { relocbuf = append(relocbuf[:0], s.P...) s.P = relocbuf + // TODO: This function call needs to be parallelized when the loader wavefront gets here. s.Attr.Set(sym.AttrReadOnly, false) } relocsym(target, reporter, lookup, archSyms, s) diff --git a/src/cmd/link/internal/ld/dwarf2.go b/src/cmd/link/internal/ld/dwarf2.go index 1dce5d7195..172c8a049e 100644 --- a/src/cmd/link/internal/ld/dwarf2.go +++ b/src/cmd/link/internal/ld/dwarf2.go @@ -106,37 +106,57 @@ func dwarfaddelfsectionsyms(ctxt *Link) { // on the fly. After this, dwarfp will contain a different (new) set of // symbols, and sections may have been replaced. func dwarfcompress(ctxt *Link) { + // compressedSect is a helper type for parallelizing compression. + type compressedSect struct { + index int + compressed []byte + syms []*sym.Symbol + } + supported := ctxt.IsELF || ctxt.HeadType == objabi.Hwindows || ctxt.HeadType == objabi.Hdarwin if !ctxt.compressDWARF || !supported || ctxt.LinkMode != LinkInternal { return } - var start int - var newDwarfp []*sym.Symbol - Segdwarf.Sections = Segdwarf.Sections[:0] + var start, compressedCount int + resChannel := make(chan compressedSect) for i, s := range dwarfp { // Find the boundaries between sections and compress // the whole section once we've found the last of its // symbols. if i+1 >= len(dwarfp) || s.Sect != dwarfp[i+1].Sect { - s1 := compressSyms(ctxt, dwarfp[start:i+1]) - if s1 == nil { - // Compression didn't help. - newDwarfp = append(newDwarfp, dwarfp[start:i+1]...) - Segdwarf.Sections = append(Segdwarf.Sections, s.Sect) - } else { - compressedSegName := ".zdebug_" + s.Sect.Name[len(".debug_"):] - sect := addsection(ctxt.Arch, &Segdwarf, compressedSegName, 04) - sect.Length = uint64(len(s1)) - newSym := ctxt.Syms.Lookup(compressedSegName, 0) - newSym.P = s1 - newSym.Size = int64(len(s1)) - newSym.Sect = sect - newDwarfp = append(newDwarfp, newSym) - } + go func(resIndex int, syms []*sym.Symbol) { + resChannel <- compressedSect{resIndex, compressSyms(ctxt, syms), syms} + }(compressedCount, dwarfp[start:i+1]) + compressedCount++ start = i + 1 } } + res := make([]compressedSect, compressedCount) + for ; compressedCount > 0; compressedCount-- { + r := <-resChannel + res[r.index] = r + } + + var newDwarfp []*sym.Symbol + Segdwarf.Sections = Segdwarf.Sections[:0] + for _, z := range res { + s := z.syms[0] + if z.compressed == nil { + // Compression didn't help. + newDwarfp = append(newDwarfp, z.syms...) + Segdwarf.Sections = append(Segdwarf.Sections, s.Sect) + } else { + compressedSegName := ".zdebug_" + s.Sect.Name[len(".debug_"):] + sect := addsection(ctxt.Arch, &Segdwarf, compressedSegName, 04) + sect.Length = uint64(len(z.compressed)) + newSym := ctxt.Syms.Lookup(compressedSegName, 0) + newSym.P = z.compressed + newSym.Size = int64(len(z.compressed)) + newSym.Sect = sect + newDwarfp = append(newDwarfp, newSym) + } + } dwarfp = newDwarfp // Re-compute the locations of the compressed DWARF symbols