Skip to content

Commit 1013ab2

Browse files
committed
Lazily, but fully load 'HeaderFileInfo' table into memory.
1 parent 88c4ef2 commit 1013ab2

File tree

3 files changed

+54
-33
lines changed

3 files changed

+54
-33
lines changed

clang/include/clang/Serialization/ASTReader.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -654,6 +654,10 @@ class ASTReader
654654
/// Map from the TU to its lexical contents from each module file.
655655
std::vector<std::pair<ModuleFile*, LexicalContents>> TULexicalDecls;
656656

657+
unsigned HeaderFileInfoIdx = 0;
658+
659+
llvm::DenseMap<FileEntryRef, HeaderFileInfo> HeaderFileInfoLookup;
660+
657661
/// Map from a DeclContext to its lookup tables.
658662
llvm::DenseMap<const DeclContext *,
659663
serialization::reader::DeclContextLookupTable> Lookups;

clang/lib/Serialization/ASTReader.cpp

Lines changed: 49 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4155,6 +4155,7 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F,
41554155
if (Record[0]) {
41564156
F.HeaderFileInfoTable = HeaderFileInfoLookupTable::Create(
41574157
(const unsigned char *)F.HeaderFileInfoTableData + Record[0],
4158+
(const unsigned char *)F.HeaderFileInfoTableData + sizeof(uint32_t),
41584159
(const unsigned char *)F.HeaderFileInfoTableData,
41594160
HeaderFileInfoTrait(*this, F));
41604161

@@ -6831,43 +6832,60 @@ std::optional<bool> ASTReader::isPreprocessedEntityInFileID(unsigned Index,
68316832
return false;
68326833
}
68336834

6834-
namespace {
6835-
6836-
/// Visitor used to search for information about a header file.
6837-
class HeaderFileInfoVisitor {
6838-
FileEntryRef FE;
6839-
std::optional<HeaderFileInfo> HFI;
6840-
6841-
public:
6842-
explicit HeaderFileInfoVisitor(FileEntryRef FE) : FE(FE) {}
6843-
6844-
bool operator()(ModuleFile &M) {
6845-
HeaderFileInfoLookupTable *Table
6846-
= static_cast<HeaderFileInfoLookupTable *>(M.HeaderFileInfoTable);
6847-
if (!Table)
6848-
return false;
6835+
static void mergeHeaderFileInfoModuleBits(HeaderFileInfo &HFI,
6836+
bool isModuleHeader,
6837+
bool isTextualModuleHeader) {
6838+
HFI.isModuleHeader |= isModuleHeader;
6839+
if (HFI.isModuleHeader)
6840+
HFI.isTextualModuleHeader = false;
6841+
else
6842+
HFI.isTextualModuleHeader |= isTextualModuleHeader;
6843+
}
68496844

6850-
// Look in the on-disk hash table for an entry for this file name.
6851-
HeaderFileInfoLookupTable::iterator Pos = Table->find(FE);
6852-
if (Pos == Table->end())
6853-
return false;
6845+
/// Merge the header file info provided by \p OtherHFI into the current
6846+
/// header file info (\p HFI)
6847+
static void mergeHeaderFileInfo(HeaderFileInfo &HFI,
6848+
const HeaderFileInfo &OtherHFI) {
6849+
assert(OtherHFI.External && "expected to merge external HFI");
68546850

6855-
HFI = *Pos;
6856-
return true;
6857-
}
6851+
HFI.isImport |= OtherHFI.isImport;
6852+
HFI.isPragmaOnce |= OtherHFI.isPragmaOnce;
6853+
mergeHeaderFileInfoModuleBits(HFI, OtherHFI.isModuleHeader,
6854+
OtherHFI.isTextualModuleHeader);
68586855

6859-
std::optional<HeaderFileInfo> getHeaderFileInfo() const { return HFI; }
6860-
};
6856+
if (!HFI.LazyControllingMacro.isValid())
6857+
HFI.LazyControllingMacro = OtherHFI.LazyControllingMacro;
68616858

6862-
} // namespace
6859+
HFI.DirInfo = OtherHFI.DirInfo;
6860+
HFI.External = (!HFI.IsValid || HFI.External);
6861+
HFI.IsValid = true;
6862+
}
68636863

68646864
HeaderFileInfo ASTReader::GetHeaderFileInfo(FileEntryRef FE) {
6865-
HeaderFileInfoVisitor Visitor(FE);
6866-
ModuleMgr.visit(Visitor);
6867-
if (std::optional<HeaderFileInfo> HFI = Visitor.getHeaderFileInfo())
6868-
return *HFI;
6869-
6870-
return HeaderFileInfo();
6865+
for (auto Iter = ModuleMgr.begin() + HeaderFileInfoIdx, End = ModuleMgr.end();
6866+
Iter != End; ++Iter) {
6867+
if (auto *Table = static_cast<HeaderFileInfoLookupTable *>(
6868+
Iter->HeaderFileInfoTable)) {
6869+
auto &Info = Table->getInfoObj();
6870+
for (auto Iter = Table->data_begin(), End = Table->data_end();
6871+
Iter != End; ++Iter) {
6872+
const auto *Item = Iter.getItem();
6873+
// Determine the length of the key and the data.
6874+
const auto& [KeyLen, DataLen] =
6875+
HeaderFileInfoTrait::ReadKeyDataLength(Item);
6876+
// Read the key.
6877+
const auto &Key = Info.ReadKey(Item, KeyLen);
6878+
if (auto EKey = Info.getFile(Key)) {
6879+
auto Data = Info.ReadData(Key, Item + KeyLen, DataLen);
6880+
auto [Iter, Inserted] = HeaderFileInfoLookup.try_emplace(*EKey, Data);
6881+
if (!Inserted)
6882+
mergeHeaderFileInfo(Iter->second, Data);
6883+
}
6884+
}
6885+
}
6886+
}
6887+
HeaderFileInfoIdx = ModuleMgr.size();
6888+
return HeaderFileInfoLookup.lookup(FE);
68716889
}
68726890

68736891
void ASTReader::ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag) {

clang/lib/Serialization/ASTReaderInternals.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -402,13 +402,12 @@ class HeaderFileInfoTrait {
402402

403403
data_type ReadData(internal_key_ref,const unsigned char *d, unsigned DataLen);
404404

405-
private:
406405
OptionalFileEntryRef getFile(const internal_key_type &Key);
407406
};
408407

409408
/// The on-disk hash table used for known header files.
410409
using HeaderFileInfoLookupTable =
411-
llvm::OnDiskChainedHashTable<HeaderFileInfoTrait>;
410+
llvm::OnDiskIterableChainedHashTable<HeaderFileInfoTrait>;
412411

413412
} // namespace reader
414413

0 commit comments

Comments
 (0)