Index: ELF/SyntheticSections.h =================================================================== --- ELF/SyntheticSections.h +++ ELF/SyntheticSections.h @@ -727,7 +727,10 @@ std::vector Chunks; // A symbol table for this .gdb_index section. - std::vector Symbols; + // The table is a vector of non-empty vectors that is + // computed parallelly, but not flattened to avoid allocating the flattened + // vector. + std::vector> Symbols; size_t Size; }; Index: ELF/SyntheticSections.cpp =================================================================== --- ELF/SyntheticSections.cpp +++ ELF/SyntheticSections.cpp @@ -2349,7 +2349,10 @@ // Returns the desired size of an on-disk hash table for a .gdb_index section. // There's a tradeoff between size and collision rate. We aim 75% utilization. size_t GdbIndexSection::computeSymtabSize() const { - return std::max(NextPowerOf2(Symbols.size() * 4 / 3), 1024); + size_t N = 0; + for (auto &Syms: Symbols) + N += Syms.size(); + return std::max(NextPowerOf2(N * 4 / 3), 1024); } // Compute the output section size. @@ -2361,7 +2364,7 @@ // Add the constant pool size if exists. if (!Symbols.empty()) { - GdbSymbol &Sym = Symbols.back(); + GdbSymbol &Sym = Symbols.back().back(); Size += Sym.NameOff + Sym.Name.size() + 1; } } @@ -2426,7 +2429,7 @@ // Create a list of symbols from a given list of symbol names and types // by uniquifying them by name. -static std::vector +static std::vector> createSymbols(ArrayRef> NameTypes) { typedef GdbIndexSection::GdbSymbol GdbSymbol; typedef GdbIndexSection::NameTypeEntry NameTypeEntry; @@ -2465,31 +2468,24 @@ } }); - 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)); + llvm::erase_if( + Symbols, [](const std::vector &Syms) { return Syms.empty(); }); // 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; - } + for (auto &Syms : Symbols) + for (GdbSymbol &Sym : Syms) { + Sym.CuVectorOff = Off; + Off += (Sym.CuVector.size() + 1) * 4; + } + for (auto &Syms : Symbols) + for (GdbSymbol &Sym : Syms) { + Sym.NameOff = Off; + Off += Sym.Name.size() + 1; + } - return Ret; + return Symbols; } // Returns a newly-created .gdb_index section. @@ -2560,34 +2556,37 @@ size_t SymtabSize = computeSymtabSize(); uint32_t Mask = SymtabSize - 1; - for (GdbSymbol &Sym : Symbols) { - uint32_t H = Sym.Name.hash(); - uint32_t I = H & Mask; - uint32_t Step = ((H * 17) & Mask) | 1; + for (auto &Syms : Symbols) + for (GdbSymbol &Sym : Syms) { + uint32_t H = Sym.Name.hash(); + uint32_t I = H & Mask; + uint32_t Step = ((H * 17) & Mask) | 1; - while (read32le(Buf + I * 8)) - I = (I + Step) & Mask; + while (read32le(Buf + I * 8)) + I = (I + Step) & Mask; - write32le(Buf + I * 8, Sym.NameOff); - write32le(Buf + I * 8 + 4, Sym.CuVectorOff); - } + write32le(Buf + I * 8, Sym.NameOff); + write32le(Buf + I * 8 + 4, Sym.CuVectorOff); + } Buf += SymtabSize * 8; // Write the string pool. Hdr->ConstantPoolOff = Buf - Start; - for (GdbSymbol &Sym : Symbols) - memcpy(Buf + Sym.NameOff, Sym.Name.data(), Sym.Name.size()); + for (auto &Syms : Symbols) + for (GdbSymbol &Sym : Syms) + memcpy(Buf + Sym.NameOff, Sym.Name.data(), Sym.Name.size()); // Write the CU vectors. - for (GdbSymbol &Sym : Symbols) { - write32le(Buf, Sym.CuVector.size()); - Buf += 4; - for (uint32_t Val : Sym.CuVector) { - write32le(Buf, Val); + for (auto &Syms : Symbols) + for (GdbSymbol &Sym : Syms) { + write32le(Buf, Sym.CuVector.size()); Buf += 4; + for (uint32_t Val : Sym.CuVector) { + write32le(Buf, Val); + Buf += 4; + } } - } } bool GdbIndexSection::empty() const { return !Out::DebugInfo; }