aboutsummaryrefslogtreecommitdiff
path: root/lib/ProfileData/Coverage/CoverageMapping.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ProfileData/Coverage/CoverageMapping.cpp')
-rw-r--r--lib/ProfileData/Coverage/CoverageMapping.cpp60
1 files changed, 56 insertions, 4 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;