diff --git a/lld/COFF/DebugTypes.h b/lld/COFF/DebugTypes.h --- a/lld/COFF/DebugTypes.h +++ b/lld/COFF/DebugTypes.h @@ -72,6 +72,9 @@ void remapRecord(MutableArrayRef rec, ArrayRef typeRefs); + void computeTypeRecordSize(llvm::codeview::CVType ty, unsigned &nbTpiRecs, + unsigned &nbIpiRecs); + void mergeTypeRecord(TypeIndex curIndex, llvm::codeview::CVType ty); // Merge the type records listed in uniqueTypes. beginIndex is the TypeIndex diff --git a/lld/COFF/DebugTypes.cpp b/lld/COFF/DebugTypes.cpp --- a/lld/COFF/DebugTypes.cpp +++ b/lld/COFF/DebugTypes.cpp @@ -620,6 +620,17 @@ }); } +void TpiSource::computeTypeRecordSize(CVType ty, unsigned &nbTpiRecs, + unsigned &nbIpiRecs) { + assert(ty.length() <= codeview::MaxRecordLength); + size_t newSize = alignTo(ty.length(), 4); + + // Decide if the merged type goes into TPI or IPI. + bool isItem = isIdRecord(ty.kind()); + + (isItem ? nbIpiRecs : nbTpiRecs) += newSize; +} + void TpiSource::mergeTypeRecord(TypeIndex curIndex, CVType ty) { // Decide if the merged type goes into TPI or IPI. bool isItem = isIdRecord(ty.kind()); @@ -679,6 +690,24 @@ auto nextUniqueIndex = uniqueTypes.begin(); assert(mergedTpi.recs.empty()); assert(mergedIpi.recs.empty()); + + // Pre-compute the number of elements in advance to avoid std::vector resizes. + unsigned nbTpiRecs = 0; + unsigned nbIpiRecs = 0; + forEachTypeChecked(typeRecords, [&](const CVType &ty) { + if (nextUniqueIndex != uniqueTypes.end() && + *nextUniqueIndex == ghashIndex) { + computeTypeRecordSize(ty, nbTpiRecs, nbIpiRecs); + ++nextUniqueIndex; + } + ++ghashIndex; + }); + mergedTpi.recs.reserve(nbTpiRecs); + mergedIpi.recs.reserve(nbIpiRecs); + + // Do the actual type merge. + ghashIndex = 0; + nextUniqueIndex = uniqueTypes.begin(); forEachTypeChecked(typeRecords, [&](const CVType &ty) { if (nextUniqueIndex != uniqueTypes.end() && *nextUniqueIndex == ghashIndex) {