diff options
Diffstat (limited to 'lib/Basic/FileManager.cpp')
-rw-r--r-- | lib/Basic/FileManager.cpp | 97 |
1 files changed, 46 insertions, 51 deletions
diff --git a/lib/Basic/FileManager.cpp b/lib/Basic/FileManager.cpp index d339b972ae8ea..f5a2d4894c13e 100644 --- a/lib/Basic/FileManager.cpp +++ b/lib/Basic/FileManager.cpp @@ -49,7 +49,7 @@ using namespace clang; //===----------------------------------------------------------------------===// FileManager::FileManager(const FileSystemOptions &FSO, - IntrusiveRefCntPtr<vfs::FileSystem> FS) + IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS) : FS(std::move(FS)), FileSystemOpts(FSO), SeenDirEntries(64), SeenFileEntries(64), NextFileUID(0) { NumDirLookups = NumFileLookups = 0; @@ -58,49 +58,17 @@ FileManager::FileManager(const FileSystemOptions &FSO, // If the caller doesn't provide a virtual file system, just grab the real // file system. if (!this->FS) - this->FS = vfs::getRealFileSystem(); + this->FS = llvm::vfs::getRealFileSystem(); } FileManager::~FileManager() = default; -void FileManager::addStatCache(std::unique_ptr<FileSystemStatCache> statCache, - bool AtBeginning) { +void FileManager::setStatCache(std::unique_ptr<FileSystemStatCache> statCache) { assert(statCache && "No stat cache provided?"); - if (AtBeginning || !StatCache.get()) { - statCache->setNextStatCache(std::move(StatCache)); - StatCache = std::move(statCache); - return; - } - - FileSystemStatCache *LastCache = StatCache.get(); - while (LastCache->getNextStatCache()) - LastCache = LastCache->getNextStatCache(); - - LastCache->setNextStatCache(std::move(statCache)); -} - -void FileManager::removeStatCache(FileSystemStatCache *statCache) { - if (!statCache) - return; - - if (StatCache.get() == statCache) { - // This is the first stat cache. - StatCache = StatCache->takeNextStatCache(); - return; - } - - // Find the stat cache in the list. - FileSystemStatCache *PrevCache = StatCache.get(); - while (PrevCache && PrevCache->getNextStatCache() != statCache) - PrevCache = PrevCache->getNextStatCache(); - - assert(PrevCache && "Stat cache not found for removal"); - PrevCache->setNextStatCache(statCache->takeNextStatCache()); + StatCache = std::move(statCache); } -void FileManager::clearStatCaches() { - StatCache.reset(); -} +void FileManager::clearStatCache() { StatCache.reset(); } /// Retrieve the directory that the given file name resides in. /// Filename can point to either a real file or a virtual file. @@ -221,15 +189,21 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile, *SeenFileEntries.insert(std::make_pair(Filename, nullptr)).first; // See if there is already an entry in the map. - if (NamedFileEnt.second) - return NamedFileEnt.second == NON_EXISTENT_FILE ? nullptr - : NamedFileEnt.second; + if (NamedFileEnt.second) { + if (NamedFileEnt.second == NON_EXISTENT_FILE) + return nullptr; + // Entry exists: return it *unless* it wasn't opened and open is requested. + if (!(NamedFileEnt.second->DeferredOpen && openFile)) + return NamedFileEnt.second; + // We previously stat()ed the file, but didn't open it: do that below. + // FIXME: the below does other redundant work too (stats the dir and file). + } else { + // By default, initialize it to invalid. + NamedFileEnt.second = NON_EXISTENT_FILE; + } ++NumFileCacheMisses; - // By default, initialize it to invalid. - NamedFileEnt.second = NON_EXISTENT_FILE; - // Get the null-terminated file name as stored as the key of the // SeenFileEntries map. StringRef InterndFileName = NamedFileEnt.first(); @@ -252,7 +226,7 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile, // FIXME: This will reduce the # syscalls. // Nope, there isn't. Check to see if the file exists. - std::unique_ptr<vfs::File> F; + std::unique_ptr<llvm::vfs::File> F; FileData Data; if (getStatValue(InterndFileName, Data, true, openFile ? &F : nullptr)) { // There's no real file at the given path. @@ -267,6 +241,7 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile, // It exists. See if we have already opened a file with the same inode. // This occurs when one dir is symlinked to another, for example. FileEntry &UFE = UniqueRealFiles[Data.UniqueID]; + UFE.DeferredOpen = !openFile; NamedFileEnt.second = &UFE; @@ -283,6 +258,15 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile, InterndFileName = NamedFileEnt.first().data(); } + // If we opened the file for the first time, record the resulting info. + // Do this even if the cache entry was valid, maybe we didn't previously open. + if (F && !UFE.File) { + if (auto PathName = F->getName()) + fillRealPathName(&UFE, *PathName); + UFE.File = std::move(F); + assert(!UFE.DeferredOpen && "we just opened it!"); + } + 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 @@ -313,11 +297,9 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile, UFE.UniqueID = Data.UniqueID; UFE.IsNamedPipe = Data.IsNamedPipe; UFE.InPCH = Data.InPCH; - UFE.File = std::move(F); UFE.IsValid = true; - if (UFE.File) - if (auto RealPathName = UFE.File->getName()) - UFE.RealPathName = *RealPathName; + // Note File and DeferredOpen were initialized above. + return &UFE; } @@ -373,6 +355,7 @@ FileManager::getVirtualFile(StringRef Filename, off_t Size, UFE->UniqueID = Data.UniqueID; UFE->IsNamedPipe = Data.IsNamedPipe; UFE->InPCH = Data.InPCH; + fillRealPathName(UFE, Data.Name); } if (!UFE) { @@ -388,6 +371,7 @@ FileManager::getVirtualFile(StringRef Filename, off_t Size, UFE->UID = NextFileUID++; UFE->IsValid = true; UFE->File.reset(); + UFE->DeferredOpen = false; return UFE; } @@ -415,6 +399,17 @@ bool FileManager::makeAbsolutePath(SmallVectorImpl<char> &Path) const { return Changed; } +void FileManager::fillRealPathName(FileEntry *UFE, llvm::StringRef FileName) { + llvm::SmallString<128> AbsPath(FileName); + // This is not the same as `VFS::getRealPath()`, which resolves symlinks + // but can be very expensive on real file systems. + // FIXME: the semantic of RealPathName is unclear, and the name might be + // misleading. We need to clean up the interface here. + makeAbsolutePath(AbsPath); + llvm::sys::path::remove_dots(AbsPath, /*remove_dot_dot=*/true); + UFE->RealPathName = AbsPath.str(); +} + llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileManager::getBufferForFile(const FileEntry *Entry, bool isVolatile, bool ShouldCloseOpenFile) { @@ -465,7 +460,7 @@ FileManager::getBufferForFile(StringRef Filename, bool isVolatile) { /// false if it's an existent real file. If FileDescriptor is NULL, /// do directory look-up instead of file look-up. bool FileManager::getStatValue(StringRef Path, FileData &Data, bool isFile, - std::unique_ptr<vfs::File> *F) { + std::unique_ptr<llvm::vfs::File> *F) { // FIXME: FileSystemOpts shouldn't be passed in here, all paths should be // absolute! if (FileSystemOpts.WorkingDir.empty()) @@ -479,11 +474,11 @@ bool FileManager::getStatValue(StringRef Path, FileData &Data, bool isFile, } bool FileManager::getNoncachedStatValue(StringRef Path, - vfs::Status &Result) { + llvm::vfs::Status &Result) { SmallString<128> FilePath(Path); FixupRelativePath(FilePath); - llvm::ErrorOr<vfs::Status> S = FS->status(FilePath.c_str()); + llvm::ErrorOr<llvm::vfs::Status> S = FS->status(FilePath.c_str()); if (!S) return true; Result = *S; |