diff options
Diffstat (limited to 'lib/ProfileData/Coverage')
-rw-r--r-- | lib/ProfileData/Coverage/CoverageMapping.cpp | 60 | ||||
-rw-r--r-- | lib/ProfileData/Coverage/CoverageMappingReader.cpp | 20 | ||||
-rw-r--r-- | lib/ProfileData/Coverage/CoverageMappingWriter.cpp | 10 |
3 files changed, 76 insertions, 14 deletions
diff --git a/lib/ProfileData/Coverage/CoverageMapping.cpp b/lib/ProfileData/Coverage/CoverageMapping.cpp index afd6618e7cb3..8d5e56e26c0f 100644 --- a/lib/ProfileData/Coverage/CoverageMapping.cpp +++ b/lib/ProfileData/Coverage/CoverageMapping.cpp @@ -194,6 +194,15 @@ void FunctionRecordIterator::skipOtherFiles() { *this = FunctionRecordIterator(); } +ArrayRef<unsigned> CoverageMapping::getImpreciseRecordIndicesForFilename( + StringRef Filename) const { + size_t FilenameHash = hash_value(Filename); + auto RecordIt = FilenameHash2RecordIndices.find(FilenameHash); + if (RecordIt == FilenameHash2RecordIndices.end()) + return {}; + return RecordIt->second; +} + Error CoverageMapping::loadFunctionRecord( const CoverageMappingRecord &Record, IndexedInstrProfReader &ProfileReader) { @@ -249,6 +258,20 @@ Error CoverageMapping::loadFunctionRecord( return Error::success(); Functions.push_back(std::move(Function)); + + // Performance optimization: keep track of the indices of the function records + // which correspond to each filename. This can be used to substantially speed + // up queries for coverage info in a file. + unsigned RecordIndex = Functions.size() - 1; + for (StringRef Filename : Record.Filenames) { + auto &RecordIndices = FilenameHash2RecordIndices[hash_value(Filename)]; + // Note that there may be duplicates in the filename set for a function + // record, because of e.g. macro expansions in the function in which both + // the macro and the function are defined in the same file. + if (RecordIndices.empty() || RecordIndices.back() != RecordIndex) + RecordIndices.push_back(RecordIndex); + } + return Error::success(); } @@ -270,6 +293,16 @@ Expected<std::unique_ptr<CoverageMapping>> CoverageMapping::load( return std::move(Coverage); } +// If E is a no_data_found error, returns success. Otherwise returns E. +static Error handleMaybeNoDataFoundError(Error E) { + return handleErrors( + std::move(E), [](const CoverageMapError &CME) { + if (CME.get() == coveragemap_error::no_data_found) + return static_cast<Error>(Error::success()); + return make_error<CoverageMapError>(CME.get()); + }); +} + Expected<std::unique_ptr<CoverageMapping>> CoverageMapping::load(ArrayRef<StringRef> ObjectFilenames, StringRef ProfileFilename, ArrayRef<StringRef> Arches) { @@ -289,12 +322,21 @@ CoverageMapping::load(ArrayRef<StringRef> ObjectFilenames, CovMappingBufOrErr.get()->getMemBufferRef(); auto CoverageReadersOrErr = BinaryCoverageReader::create(CovMappingBufRef, Arch, Buffers); - if (Error E = CoverageReadersOrErr.takeError()) - return std::move(E); + if (Error E = CoverageReadersOrErr.takeError()) { + E = handleMaybeNoDataFoundError(std::move(E)); + if (E) + return std::move(E); + // E == success (originally a no_data_found error). + continue; + } for (auto &Reader : CoverageReadersOrErr.get()) Readers.push_back(std::move(Reader)); Buffers.push_back(std::move(CovMappingBufOrErr.get())); } + // If no readers were created, either no objects were provided or none of them + // had coverage data. Return an error in the latter case. + if (Readers.empty() && !ObjectFilenames.empty()) + return make_error<CoverageMapError>(coveragemap_error::no_data_found); return load(Readers, *ProfileReader); } @@ -607,7 +649,12 @@ CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) const { CoverageData FileCoverage(Filename); std::vector<CountedRegion> Regions; - for (const auto &Function : Functions) { + // Look up the function records in the given file. Due to hash collisions on + // the filename, we may get back some records that are not in the file. + ArrayRef<unsigned> RecordIndices = + getImpreciseRecordIndicesForFilename(Filename); + for (unsigned RecordIndex : RecordIndices) { + const FunctionRecord &Function = Functions[RecordIndex]; auto MainFileID = findMainViewFileID(Filename, Function); auto FileIDs = gatherFileIDs(Filename, Function); for (const auto &CR : Function.CountedRegions) @@ -627,7 +674,12 @@ CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) const { std::vector<InstantiationGroup> CoverageMapping::getInstantiationGroups(StringRef Filename) const { FunctionInstantiationSetCollector InstantiationSetCollector; - for (const auto &Function : Functions) { + // Look up the function records in the given file. Due to hash collisions on + // the filename, we may get back some records that are not in the file. + ArrayRef<unsigned> RecordIndices = + getImpreciseRecordIndicesForFilename(Filename); + for (unsigned RecordIndex : RecordIndices) { + const FunctionRecord &Function = Functions[RecordIndex]; auto MainFileID = findMainViewFileID(Filename, Function); if (!MainFileID) continue; diff --git a/lib/ProfileData/Coverage/CoverageMappingReader.cpp b/lib/ProfileData/Coverage/CoverageMappingReader.cpp index e193e10f91d9..679ff3525eeb 100644 --- a/lib/ProfileData/Coverage/CoverageMappingReader.cpp +++ b/lib/ProfileData/Coverage/CoverageMappingReader.cpp @@ -506,7 +506,7 @@ public: return make_error<CoverageMapError>(coveragemap_error::malformed); // Each coverage map has an alignment of 8, so we need to adjust alignment // before reading the next map. - Buf += alignmentAdjustment(Buf, 8); + Buf += offsetToAlignedAddr(Buf, Align(8)); auto CFR = reinterpret_cast<const FuncRecordType *>(FunBuf); while ((const char *)CFR < FunEnd) { @@ -539,7 +539,7 @@ Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get( switch (Version) { case CovMapVersion::Version1: - return llvm::make_unique<VersionedCovMapFuncRecordReader< + return std::make_unique<VersionedCovMapFuncRecordReader< CovMapVersion::Version1, IntPtrT, Endian>>(P, R, F); case CovMapVersion::Version2: case CovMapVersion::Version3: @@ -547,10 +547,10 @@ Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get( if (Error E = P.create(P.getNameData())) return std::move(E); if (Version == CovMapVersion::Version2) - return llvm::make_unique<VersionedCovMapFuncRecordReader< + return std::make_unique<VersionedCovMapFuncRecordReader< CovMapVersion::Version2, IntPtrT, Endian>>(P, R, F); else - return llvm::make_unique<VersionedCovMapFuncRecordReader< + return std::make_unique<VersionedCovMapFuncRecordReader< CovMapVersion::Version3, IntPtrT, Endian>>(P, R, F); } llvm_unreachable("Unsupported version"); @@ -648,7 +648,7 @@ loadTestingFormat(StringRef Data) { // Skip the padding bytes because coverage map data has an alignment of 8. if (CoverageMapping.empty()) return make_error<CoverageMapError>(coveragemap_error::truncated); - size_t Pad = alignmentAdjustment(CoverageMapping.data(), 8); + size_t Pad = offsetToAlignedAddr(CoverageMapping.data(), Align(8)); if (CoverageMapping.size() < Pad) return make_error<CoverageMapError>(coveragemap_error::malformed); CoverageMapping = CoverageMapping.substr(Pad); @@ -666,11 +666,11 @@ static Expected<SectionRef> lookupSection(ObjectFile &OF, StringRef Name) { }; Name = stripSuffix(Name); - StringRef FoundName; for (const auto &Section : OF.sections()) { - if (auto EC = Section.getName(FoundName)) - return errorCodeToError(EC); - if (stripSuffix(FoundName) == Name) + Expected<StringRef> NameOrErr = Section.getName(); + if (!NameOrErr) + return NameOrErr.takeError(); + if (stripSuffix(*NameOrErr) == Name) return Section; } return make_error<CoverageMapError>(coveragemap_error::no_data_found); @@ -682,7 +682,7 @@ loadBinaryFormat(std::unique_ptr<Binary> Bin, StringRef Arch) { if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) { // If we have a universal binary, try to look up the object for the // appropriate architecture. - auto ObjectFileOrErr = Universal->getObjectForArch(Arch); + auto ObjectFileOrErr = Universal->getMachOObjectForArch(Arch); if (!ObjectFileOrErr) return ObjectFileOrErr.takeError(); OF = std::move(ObjectFileOrErr.get()); diff --git a/lib/ProfileData/Coverage/CoverageMappingWriter.cpp b/lib/ProfileData/Coverage/CoverageMappingWriter.cpp index 432b20f217ca..d75854a60d1e 100644 --- a/lib/ProfileData/Coverage/CoverageMappingWriter.cpp +++ b/lib/ProfileData/Coverage/CoverageMappingWriter.cpp @@ -24,6 +24,16 @@ using namespace llvm; using namespace coverage; +CoverageFilenamesSectionWriter::CoverageFilenamesSectionWriter( + ArrayRef<StringRef> Filenames) + : Filenames(Filenames) { +#ifndef NDEBUG + StringSet<> NameSet; + for (StringRef Name : Filenames) + assert(NameSet.insert(Name).second && "Duplicate filename"); +#endif +} + void CoverageFilenamesSectionWriter::write(raw_ostream &OS) { encodeULEB128(Filenames.size(), OS); for (const auto &Filename : Filenames) { |