Index: ELF/SyntheticSections.cpp =================================================================== --- ELF/SyntheticSections.cpp +++ ELF/SyntheticSections.cpp @@ -2449,13 +2449,14 @@ } template -static std::vector +static void readPubNamesAndTypes(const LLDDwarfObj &Obj, - const std::vector &CUs) { + const std::vector &CUs, + std::vector &Ret) { const DWARFSection &PubNames = Obj.getGnuPubNamesSection(); const DWARFSection &PubTypes = Obj.getGnuPubTypesSection(); - std::vector Ret; + Ret.clear(); for (const DWARFSection *Pub : {&PubNames, &PubTypes}) { DWARFDebugPubTable Table(Obj, *Pub, Config->IsLE, true); for (const DWARFDebugPubTable::Set &Set : Table.getData()) { @@ -2474,91 +2475,13 @@ (Ent.Descriptor.toBits() << 24) | I}); } } - return Ret; -} - -// Create a list of symbols from a given list of symbol names and types -// by uniquifying them by name. -static std::vector -createSymbols(ArrayRef> NameAttrs, - const std::vector &Chunks) { - typedef GdbIndexSection::GdbSymbol GdbSymbol; - typedef GdbIndexSection::NameAttrEntry NameAttrEntry; - - // For each chunk, compute the number of compilation units preceding it. - uint32_t CuIdx = 0; - std::vector CuIdxs(Chunks.size()); - for (uint32_t I = 0, E = Chunks.size(); I != E; ++I) { - CuIdxs[I] = CuIdx; - CuIdx += Chunks[I].CompilationUnits.size(); - } - - // The number of symbols we will handle in this function is of the order - // of millions for very large executables, so we use multi-threading to - // speed it up. - size_t NumShards = 32; - size_t Concurrency = 1; - if (ThreadsEnabled) - Concurrency = - std::min(PowerOf2Floor(hardware_concurrency()), NumShards); - - // A sharded map to uniquify symbols by name. - std::vector> Map(NumShards); - size_t Shift = 32 - countTrailingZeros(NumShards); - - // Instantiate GdbSymbols while uniqufying them by name. - std::vector> Symbols(NumShards); - parallelForEachN(0, Concurrency, [&](size_t ThreadId) { - uint32_t I = 0; - for (ArrayRef Entries : NameAttrs) { - for (const NameAttrEntry &Ent : Entries) { - size_t ShardId = Ent.Name.hash() >> Shift; - if ((ShardId & (Concurrency - 1)) != ThreadId) - continue; - - uint32_t V = Ent.CuIndexAndAttrs + CuIdxs[I]; - size_t &Idx = Map[ShardId][Ent.Name]; - if (Idx) { - Symbols[ShardId][Idx - 1].CuVector.push_back(V); - continue; - } - - Idx = Symbols[ShardId].size() + 1; - Symbols[ShardId].push_back({Ent.Name, {V}, 0, 0}); - } - ++I; - } - }); - - size_t NumSymbols = 0; - for (ArrayRef V : Symbols) - NumSymbols += V.size(); - - // The return type is a flattened vector, so we'll copy each vector - // contents to Ret. - std::vector Ret; - Ret.reserve(NumSymbols); - for (std::vector &Vec : Symbols) - for (GdbSymbol &Sym : Vec) - Ret.push_back(std::move(Sym)); - - // CU vectors and symbol names are adjacent in the output file. - // We can compute their offsets in the output file now. - size_t Off = 0; - for (GdbSymbol &Sym : Ret) { - Sym.CuVectorOff = Off; - Off += (Sym.CuVector.size() + 1) * 4; - } - for (GdbSymbol &Sym : Ret) { - Sym.NameOff = Off; - Off += Sym.Name.size() + 1; - } - - return Ret; } // Returns a newly-created .gdb_index section. template GdbIndexSection *GdbIndexSection::create() { + typedef GdbIndexSection::GdbSymbol GdbSymbol; + typedef GdbIndexSection::NameAttrEntry NameAttrEntry; + std::vector Sections = getDebugInfoSections(); // .debug_gnu_pub{names,types} are useless in executables. @@ -2569,23 +2492,58 @@ S->Live = false; std::vector Chunks(Sections.size()); - std::vector> NameAttrs(Sections.size()); + std::vector Symbols; + + DenseMap Map; + std::vector CuIdxs(Chunks.size()); parallelForEachN(0, Sections.size(), [&](size_t I) { ObjFile *File = Sections[I]->getFile(); DWARFContext Dwarf(make_unique>(File)); - Chunks[I].Sec = Sections[I]; Chunks[I].CompilationUnits = readCuList(Dwarf); Chunks[I].AddressAreas = readAddressAreas(Dwarf, Sections[I]); - NameAttrs[I] = readPubNamesAndTypes( + }); + uint32_t CuIdx = 0; + for (uint32_t I = 0, E = Chunks.size(); I != E; ++I) { + CuIdxs[I] = CuIdx; + CuIdx += Chunks[I].CompilationUnits.size(); + } + + std::mutex Mutex; + parallelForEachN(0, Sections.size(), [&](size_t I) { + ObjFile *File = Sections[I]->getFile(); + DWARFContext Dwarf(make_unique>(File)); + std::vector NameAttrs; + readPubNamesAndTypes( static_cast &>(Dwarf.getDWARFObj()), - Chunks[I].CompilationUnits); + Chunks[I].CompilationUnits, NameAttrs); + std::lock_guard Lock(Mutex); + for (NameAttrEntry &Ent : NameAttrs) { + auto R = Map.try_emplace(Ent.Name, Symbols.size()); + if (R.second) + Symbols.push_back({Ent.Name, {}, 0, 0}); + Symbols[R.first->second].CuVector.push_back(Ent.CuIndexAndAttrs + + CuIdxs[I]); + } }); + // CU vectors and symbol names are adjacent in the output file. + // We can compute their offsets in the output file now. + uint32_t Off = 0; + for (GdbSymbol &Sym : Symbols) { + Sym.CuVectorOff = Off; + Off += (1 + Sym.CuVector.size()) * 4; + } + + for (GdbSymbol &Sym : Symbols) { + Sym.NameOff = Off; + Off += Sym.Name.size() + 1; + } + auto *Ret = make(); Ret->Chunks = std::move(Chunks); - Ret->Symbols = createSymbols(NameAttrs, Ret->Chunks); + Ret->Symbols = std::move(Symbols); Ret->initOutputSize(); return Ret; }