@@ -194,6 +194,15 @@ void FunctionRecordIterator::skipOtherFiles() {
194
194
*this = FunctionRecordIterator ();
195
195
}
196
196
197
+ ArrayRef<unsigned > CoverageMapping::getImpreciseRecordIndicesForFilename (
198
+ StringRef Filename) const {
199
+ size_t FilenameHash = hash_value (Filename);
200
+ auto RecordIt = FilenameHash2RecordIndices.find (FilenameHash);
201
+ if (RecordIt == FilenameHash2RecordIndices.end ())
202
+ return {};
203
+ return RecordIt->second ;
204
+ }
205
+
197
206
Error CoverageMapping::loadFunctionRecord (
198
207
const CoverageMappingRecord &Record,
199
208
IndexedInstrProfReader &ProfileReader) {
@@ -249,6 +258,20 @@ Error CoverageMapping::loadFunctionRecord(
249
258
return Error::success ();
250
259
251
260
Functions.push_back (std::move (Function));
261
+
262
+ // Performance optimization: keep track of the indices of the function records
263
+ // which correspond to each filename. This can be used to substantially speed
264
+ // up queries for coverage info in a file.
265
+ unsigned RecordIndex = Functions.size () - 1 ;
266
+ for (StringRef Filename : Record.Filenames ) {
267
+ auto &RecordIndices = FilenameHash2RecordIndices[hash_value (Filename)];
268
+ // Note that there may be duplicates in the filename set for a function
269
+ // record, because of e.g. macro expansions in the function in which both
270
+ // the macro and the function are defined in the same file.
271
+ if (RecordIndices.empty () || RecordIndices.back () != RecordIndex)
272
+ RecordIndices.push_back (RecordIndex);
273
+ }
274
+
252
275
return Error::success ();
253
276
}
254
277
@@ -626,7 +649,12 @@ CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) const {
626
649
CoverageData FileCoverage (Filename);
627
650
std::vector<CountedRegion> Regions;
628
651
629
- for (const auto &Function : Functions) {
652
+ // Look up the function records in the given file. Due to hash collisions on
653
+ // the filename, we may get back some records that are not in the file.
654
+ ArrayRef<unsigned > RecordIndices =
655
+ getImpreciseRecordIndicesForFilename (Filename);
656
+ for (unsigned RecordIndex : RecordIndices) {
657
+ const FunctionRecord &Function = Functions[RecordIndex];
630
658
auto MainFileID = findMainViewFileID (Filename, Function);
631
659
auto FileIDs = gatherFileIDs (Filename, Function);
632
660
for (const auto &CR : Function.CountedRegions )
@@ -646,7 +674,12 @@ CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) const {
646
674
std::vector<InstantiationGroup>
647
675
CoverageMapping::getInstantiationGroups (StringRef Filename) const {
648
676
FunctionInstantiationSetCollector InstantiationSetCollector;
649
- for (const auto &Function : Functions) {
677
+ // Look up the function records in the given file. Due to hash collisions on
678
+ // the filename, we may get back some records that are not in the file.
679
+ ArrayRef<unsigned > RecordIndices =
680
+ getImpreciseRecordIndicesForFilename (Filename);
681
+ for (unsigned RecordIndex : RecordIndices) {
682
+ const FunctionRecord &Function = Functions[RecordIndex];
650
683
auto MainFileID = findMainViewFileID (Filename, Function);
651
684
if (!MainFileID)
652
685
continue ;
0 commit comments