diff options
author | Duncan P. N. Exon Smith <dexonsmith@apple.com> | 2020-10-15 11:39:07 -0400 |
---|---|---|
committer | Duncan P. N. Exon Smith <dexonsmith@apple.com> | 2020-10-27 14:55:41 -0400 |
commit | 917acac960d40280ea02ea453e594034b1be1f6b (patch) | |
tree | 77725736105c187559617b78904af3ede6fee5f7 /clang/lib/Basic/FileManager.cpp | |
parent | 83154c541806468802d687a8b3c8f1a65e92199c (diff) | |
download | llvm-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.cpp | 106 |
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; } |