Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 44 additions & 2 deletions clang/include/clang/Serialization/ModuleManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,50 @@ class ModuleManager {
// to implement short-circuiting logic when running DFS over the dependencies.
SmallVector<ModuleFile *, 2> Roots;

/// An \c EntryKey is a thin wrapper around a \c FileEntry that implements
/// a richer notion of identity.
///
/// A plain \c FileEntry has its identity tied to inode numbers. When the
/// module cache regenerates a PCM, some filesystem allocators may reuse
/// inode numbers for distinct modules, which can cause the cache to return
/// mismatched entries. An \c EntryKey ensures that the size and modification
/// time are taken into account when determining the identity of a key, which
/// significantly decreases - but does not eliminate - the chance of
/// a collision.
struct EntryKey {
const FileEntry *Entry;

struct Info {
static inline EntryKey getEmptyKey() {
return EntryKey{llvm::DenseMapInfo<const FileEntry *>::getEmptyKey()};
}
static inline EntryKey getTombstoneKey() {
return EntryKey{
llvm::DenseMapInfo<const FileEntry *>::getTombstoneKey()};
}
static unsigned getHashValue(const EntryKey &Val) {
return llvm::DenseMapInfo<const FileEntry *>::getHashValue(Val.Entry);
}
static bool isEqual(const EntryKey &LHS, const EntryKey &RHS) {
if (LHS.Entry == getEmptyKey().Entry ||
LHS.Entry == getTombstoneKey().Entry ||
RHS.Entry == getEmptyKey().Entry ||
RHS.Entry == getTombstoneKey().Entry) {
return LHS.Entry == RHS.Entry;
}
if (LHS.Entry == nullptr || RHS.Entry == nullptr) {
return LHS.Entry == RHS.Entry;
}
return LHS.Entry == RHS.Entry &&
LHS.Entry->getSize() == RHS.Entry->getSize() &&
LHS.Entry->getModificationTime() ==
RHS.Entry->getModificationTime();
}
};
};

/// All loaded modules, indexed by name.
llvm::DenseMap<const FileEntry *, ModuleFile *> Modules;
llvm::DenseMap<EntryKey, ModuleFile *, EntryKey::Info> Modules;

/// FileManager that handles translating between filenames and
/// FileEntry *.
Expand All @@ -76,7 +118,7 @@ class ModuleManager {
const HeaderSearch &HeaderSearchInfo;

/// A lookup of in-memory (virtual file) buffers
llvm::DenseMap<const FileEntry *, std::unique_ptr<llvm::MemoryBuffer>>
llvm::DenseMap<EntryKey, std::unique_ptr<llvm::MemoryBuffer>, EntryKey::Info>
InMemoryBuffers;

/// The visitation order.
Expand Down
12 changes: 6 additions & 6 deletions clang/lib/Serialization/ModuleManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ ModuleFile *ModuleManager::lookupByModuleName(StringRef Name) const {
}

ModuleFile *ModuleManager::lookup(const FileEntry *File) const {
auto Known = Modules.find(File);
auto Known = Modules.find(EntryKey{File});
if (Known == Modules.end())
return nullptr;

Expand All @@ -72,7 +72,7 @@ ModuleManager::lookupBuffer(StringRef Name) {
/*CacheFailure=*/false);
if (!Entry)
return nullptr;
return std::move(InMemoryBuffers[*Entry]);
return std::move(InMemoryBuffers[EntryKey{*Entry}]);
}

static bool checkSignature(ASTFileSignature Signature,
Expand Down Expand Up @@ -133,7 +133,7 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type,
}

// Check whether we already loaded this module, before
if (ModuleFile *ModuleEntry = Modules.lookup(Entry)) {
if (ModuleFile *ModuleEntry = Modules.lookup(EntryKey{Entry})) {
// Check the stored signature.
if (checkSignature(ModuleEntry->Signature, ExpectedSignature, ErrorStr))
return OutOfDate;
Expand Down Expand Up @@ -213,7 +213,7 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type,
return OutOfDate;

// We're keeping this module. Store it everywhere.
Module = Modules[Entry] = NewModule.get();
Module = Modules[EntryKey{Entry}] = NewModule.get();

updateModuleImports(*NewModule, ImportedBy, ImportLoc);

Expand Down Expand Up @@ -260,7 +260,7 @@ void ModuleManager::removeModules(ModuleIterator First, ModuleMap *modMap) {

// Delete the modules and erase them from the various structures.
for (ModuleIterator victim = First; victim != Last; ++victim) {
Modules.erase(victim->File);
Modules.erase(EntryKey{victim->File});

if (modMap) {
StringRef ModuleName = victim->ModuleName;
Expand All @@ -279,7 +279,7 @@ ModuleManager::addInMemoryBuffer(StringRef FileName,
std::unique_ptr<llvm::MemoryBuffer> Buffer) {
const FileEntry *Entry =
FileMgr.getVirtualFile(FileName, Buffer->getBufferSize(), 0);
InMemoryBuffers[Entry] = std::move(Buffer);
InMemoryBuffers[EntryKey{Entry}] = std::move(Buffer);
}

ModuleManager::VisitState *ModuleManager::allocateVisitState() {
Expand Down