diff options
Diffstat (limited to 'lib/ProfileData/Coverage/CoverageMapping.cpp')
| -rw-r--r-- | lib/ProfileData/Coverage/CoverageMapping.cpp | 60 | 
1 files changed, 56 insertions, 4 deletions
diff --git a/lib/ProfileData/Coverage/CoverageMapping.cpp b/lib/ProfileData/Coverage/CoverageMapping.cpp index afd6618e7cb3e..8d5e56e26c0ff 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;  | 
