aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Basic/FileManager.cpp
diff options
context:
space:
mode:
authorDuncan P. N. Exon Smith <dexonsmith@apple.com>2020-10-15 11:39:07 -0400
committerDuncan P. N. Exon Smith <dexonsmith@apple.com>2020-10-27 14:55:41 -0400
commit917acac960d40280ea02ea453e594034b1be1f6b (patch)
tree77725736105c187559617b78904af3ede6fee5f7 /clang/lib/Basic/FileManager.cpp
parent83154c541806468802d687a8b3c8f1a65e92199c (diff)
downloadllvm-917acac960d40280ea02ea453e594034b1be1f6b.zip
llvm-917acac960d40280ea02ea453e594034b1be1f6b.tar.gz
llvm-917acac960d40280ea02ea453e594034b1be1f6b.tar.bz2
FileManager: Shrink FileEntryRef to the size of a pointer
Shrink `FileEntryRef` to the size of a pointer, by having it directly reference the `StringMapEntry` the same way that `DirectoryEntryRef` does. This makes `FileEntryRef::FileEntryRef` private as a side effect (`FileManager` is a friend!). There are two helper types added within `FileEntryRef`: - `FileEntryRef::MapValue` is the type stored in `FileManager::SeenFileEntries`. It's a replacement for `SeenFileEntryOrRedirect`, where the second pointer type has been changed from `StringRef*` to `MapEntry*` (see next bullet). - `FileEntryRef::MapEntry` is the instantiation of `StringMapEntry<>` where `MapValue` is stored. This is what `FileEntryRef` has a pointer to, in order to grab the name in addition to the value. Differential Revision: https://reviews.llvm.org/D89488
Diffstat (limited to 'clang/lib/Basic/FileManager.cpp')
-rw-r--r--clang/lib/Basic/FileManager.cpp106
1 files changed, 62 insertions, 44 deletions
diff --git a/clang/lib/Basic/FileManager.cpp b/clang/lib/Basic/FileManager.cpp
index e92e9d5..d26ead4 100644
--- a/clang/lib/Basic/FileManager.cpp
+++ b/clang/lib/Basic/FileManager.cpp
@@ -212,11 +212,10 @@ FileManager::getFileRef(StringRef Filename, bool openFile, bool CacheFailure) {
SeenFileInsertResult.first->second.getError());
// Construct and return and FileEntryRef, unless it's a redirect to another
// filename.
- SeenFileEntryOrRedirect Value = *SeenFileInsertResult.first->second;
- FileEntry *FE;
- if (LLVM_LIKELY(FE = Value.dyn_cast<FileEntry *>()))
- return FileEntryRef(SeenFileInsertResult.first->first(), *FE);
- return getFileRef(*Value.get<const StringRef *>(), openFile, CacheFailure);
+ FileEntryRef::MapValue Value = *SeenFileInsertResult.first->second;
+ if (LLVM_LIKELY(Value.V.is<FileEntry *>()))
+ return FileEntryRef(*SeenFileInsertResult.first);
+ return FileEntryRef(*Value.V.get<const FileEntryRef::MapEntry *>());
}
// We've not seen this before. Fill it in.
@@ -268,26 +267,29 @@ FileManager::getFileRef(StringRef Filename, bool openFile, bool CacheFailure) {
// This occurs when one dir is symlinked to another, for example.
FileEntry &UFE = UniqueRealFiles[Status.getUniqueID()];
- NamedFileEnt->second = &UFE;
-
- // If the name returned by getStatValue is different than Filename, re-intern
- // the name.
- if (Status.getName() != Filename) {
- auto &NewNamedFileEnt =
- *SeenFileEntries.insert({Status.getName(), &UFE}).first;
- assert((*NewNamedFileEnt.second).get<FileEntry *>() == &UFE &&
+ if (Status.getName() == Filename) {
+ // The name matches. Set the FileEntry.
+ NamedFileEnt->second = FileEntryRef::MapValue(UFE);
+ } else {
+ // Name mismatch. We need a redirect. First grab the actual entry we want
+ // to return.
+ auto &Redirection =
+ *SeenFileEntries.insert({Status.getName(), FileEntryRef::MapValue(UFE)})
+ .first;
+ assert(Redirection.second->V.is<FileEntry *>() &&
+ "filename redirected to a non-canonical filename?");
+ assert(Redirection.second->V.get<FileEntry *>() == &UFE &&
"filename from getStatValue() refers to wrong file");
- InterndFileName = NewNamedFileEnt.first().data();
- // In addition to re-interning the name, construct a redirecting seen file
- // entry, that will point to the name the filesystem actually wants to use.
- StringRef *Redirect = new (CanonicalNameStorage) StringRef(InterndFileName);
- auto SeenFileInsertResultIt = SeenFileEntries.find(Filename);
- assert(SeenFileInsertResultIt != SeenFileEntries.end() &&
- "unexpected SeenFileEntries cache miss");
- SeenFileInsertResultIt->second = Redirect;
- NamedFileEnt = &*SeenFileInsertResultIt;
+
+ // Cache the redirection in the previously-inserted entry, still available
+ // in the tentative return value.
+ NamedFileEnt->second = FileEntryRef::MapValue(Redirection);
+
+ // Fix the tentative return value.
+ NamedFileEnt = &Redirection;
}
+ FileEntryRef ReturnedRef(*NamedFileEnt);
if (UFE.isValid()) { // Already have an entry with this inode, return it.
// FIXME: this hack ensures that if we look up a file by a virtual path in
@@ -299,20 +301,20 @@ FileManager::getFileRef(StringRef Filename, bool openFile, bool CacheFailure) {
if (DirInfo != UFE.Dir && Status.IsVFSMapped)
UFE.Dir = DirInfo;
- // Always update the name to use the last name by which a file was accessed.
- // FIXME: Neither this nor always using the first name is correct; we want
- // to switch towards a design where we return a FileName object that
+ // Always update LastRef to the last name by which a file was accessed.
+ // FIXME: Neither this nor always using the first reference is correct; we
+ // want to switch towards a design where we return a FileName object that
// encapsulates both the name by which the file was accessed and the
// corresponding FileEntry.
- // FIXME: The Name should be removed from FileEntry once all clients
- // adopt FileEntryRef.
- UFE.Name = InterndFileName;
+ // FIXME: LastRef should be removed from FileEntry once all clients adopt
+ // FileEntryRef.
+ UFE.LastRef = ReturnedRef;
- return FileEntryRef(InterndFileName, UFE);
+ return ReturnedRef;
}
// Otherwise, we don't have this file yet, add it.
- UFE.Name = InterndFileName;
+ UFE.LastRef = ReturnedRef;
UFE.Size = Status.getSize();
UFE.ModTime = llvm::sys::toTimeT(Status.getLastModificationTime());
UFE.Dir = DirInfo;
@@ -329,7 +331,7 @@ FileManager::getFileRef(StringRef Filename, bool openFile, bool CacheFailure) {
// We should still fill the path even if we aren't opening the file.
fillRealPathName(&UFE, InterndFileName);
}
- return FileEntryRef(InterndFileName, UFE);
+ return ReturnedRef;
}
const FileEntry *
@@ -341,12 +343,12 @@ FileManager::getVirtualFile(StringRef Filename, off_t Size,
auto &NamedFileEnt = *SeenFileEntries.insert(
{Filename, std::errc::no_such_file_or_directory}).first;
if (NamedFileEnt.second) {
- SeenFileEntryOrRedirect Value = *NamedFileEnt.second;
+ FileEntryRef::MapValue Value = *NamedFileEnt.second;
FileEntry *FE;
- if (LLVM_LIKELY(FE = Value.dyn_cast<FileEntry *>()))
+ if (LLVM_LIKELY(FE = Value.V.dyn_cast<FileEntry *>()))
return FE;
- return getVirtualFile(*Value.get<const StringRef *>(), Size,
- ModificationTime);
+ return &FileEntryRef(*Value.V.get<const FileEntryRef::MapEntry *>())
+ .getFileEntry();
}
// We've not seen this before, or the file is cached as non-existent.
@@ -372,7 +374,7 @@ FileManager::getVirtualFile(StringRef Filename, off_t Size,
Status.getUser(), Status.getGroup(), Size,
Status.getType(), Status.getPermissions());
- NamedFileEnt.second = UFE;
+ NamedFileEnt.second = FileEntryRef::MapValue(*UFE);
// If we had already opened this file, close it now so we don't
// leak the descriptor. We're not going to use the file
@@ -381,6 +383,9 @@ FileManager::getVirtualFile(StringRef Filename, off_t Size,
UFE->closeFile();
// If we already have an entry with this inode, return it.
+ //
+ // FIXME: Surely this should add a reference by the new name, and return
+ // it instead...
if (UFE->isValid())
return UFE;
@@ -390,10 +395,10 @@ FileManager::getVirtualFile(StringRef Filename, off_t Size,
} else {
VirtualFileEntries.push_back(std::make_unique<FileEntry>());
UFE = VirtualFileEntries.back().get();
- NamedFileEnt.second = UFE;
+ NamedFileEnt.second = FileEntryRef::MapValue(*UFE);
}
- UFE->Name = InterndFileName;
+ UFE->LastRef = FileEntryRef(NamedFileEnt);
UFE->Size = Size;
UFE->ModTime = ModificationTime;
UFE->Dir = *DirInfo;
@@ -409,17 +414,30 @@ llvm::Optional<FileEntryRef> FileManager::getBypassFile(FileEntryRef VF) {
if (getStatValue(VF.getName(), Status, /*isFile=*/true, /*F=*/nullptr))
return None;
- // Fill it in from the stat.
+ if (!SeenBypassFileEntries)
+ SeenBypassFileEntries = std::make_unique<
+ llvm::StringMap<llvm::ErrorOr<FileEntryRef::MapValue>>>();
+
+ // If we've already bypassed just use the existing one.
+ auto Insertion = SeenBypassFileEntries->insert(
+ {VF.getName(), std::errc::no_such_file_or_directory});
+ if (!Insertion.second)
+ return FileEntryRef(*Insertion.first);
+
+ // Fill in the new entry from the stat.
BypassFileEntries.push_back(std::make_unique<FileEntry>());
const FileEntry &VFE = VF.getFileEntry();
FileEntry &BFE = *BypassFileEntries.back();
- BFE.Name = VFE.getName();
+ Insertion.first->second = FileEntryRef::MapValue(BFE);
+ BFE.LastRef = FileEntryRef(*Insertion.first);
BFE.Size = Status.getSize();
BFE.Dir = VFE.Dir;
BFE.ModTime = llvm::sys::toTimeT(Status.getLastModificationTime());
BFE.UID = NextFileUID++;
BFE.IsValid = true;
- return FileEntryRef(VF.getName(), BFE);
+
+ // Save the entry in the bypass table and return.
+ return FileEntryRef(*Insertion.first);
}
bool FileManager::FixupRelativePath(SmallVectorImpl<char> &path) const {
@@ -534,13 +552,13 @@ void FileManager::GetUniqueIDMapping(
UIDToFiles.resize(NextFileUID);
// Map file entries
- for (llvm::StringMap<llvm::ErrorOr<SeenFileEntryOrRedirect>,
+ for (llvm::StringMap<llvm::ErrorOr<FileEntryRef::MapValue>,
llvm::BumpPtrAllocator>::const_iterator
FE = SeenFileEntries.begin(),
FEEnd = SeenFileEntries.end();
FE != FEEnd; ++FE)
- if (llvm::ErrorOr<SeenFileEntryOrRedirect> Entry = FE->getValue()) {
- if (const auto *FE = (*Entry).dyn_cast<FileEntry *>())
+ if (llvm::ErrorOr<FileEntryRef::MapValue> Entry = FE->getValue()) {
+ if (const auto *FE = Entry->V.dyn_cast<FileEntry *>())
UIDToFiles[FE->getUID()] = FE;
}