forked from OSchip/llvm-project
FileManager: std::map => BumpPtrAllocator + DenseMap of pointers. NFC
This is both smaller and faster. Differential Revision: https://reviews.llvm.org/D123144
This commit is contained in:
parent
79ad5fb295
commit
cf1c5507b7
|
@ -53,24 +53,26 @@ class FileSystemStatCache;
|
||||||
class FileManager : public RefCountedBase<FileManager> {
|
class FileManager : public RefCountedBase<FileManager> {
|
||||||
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS;
|
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS;
|
||||||
FileSystemOptions FileSystemOpts;
|
FileSystemOptions FileSystemOpts;
|
||||||
|
llvm::SpecificBumpPtrAllocator<FileEntry> FilesAlloc;
|
||||||
|
llvm::SpecificBumpPtrAllocator<DirectoryEntry> DirsAlloc;
|
||||||
|
|
||||||
/// Cache for existing real directories.
|
/// Cache for existing real directories.
|
||||||
std::map<llvm::sys::fs::UniqueID, DirectoryEntry> UniqueRealDirs;
|
llvm::DenseMap<llvm::sys::fs::UniqueID, DirectoryEntry *> UniqueRealDirs;
|
||||||
|
|
||||||
/// Cache for existing real files.
|
/// Cache for existing real files.
|
||||||
std::map<llvm::sys::fs::UniqueID, FileEntry> UniqueRealFiles;
|
llvm::DenseMap<llvm::sys::fs::UniqueID, FileEntry *> UniqueRealFiles;
|
||||||
|
|
||||||
/// The virtual directories that we have allocated.
|
/// The virtual directories that we have allocated.
|
||||||
///
|
///
|
||||||
/// For each virtual file (e.g. foo/bar/baz.cpp), we add all of its parent
|
/// For each virtual file (e.g. foo/bar/baz.cpp), we add all of its parent
|
||||||
/// directories (foo/ and foo/bar/) here.
|
/// directories (foo/ and foo/bar/) here.
|
||||||
SmallVector<std::unique_ptr<DirectoryEntry>, 4> VirtualDirectoryEntries;
|
SmallVector<DirectoryEntry *, 4> VirtualDirectoryEntries;
|
||||||
/// The virtual files that we have allocated.
|
/// The virtual files that we have allocated.
|
||||||
SmallVector<std::unique_ptr<FileEntry>, 4> VirtualFileEntries;
|
SmallVector<FileEntry *, 4> VirtualFileEntries;
|
||||||
|
|
||||||
/// A set of files that bypass the maps and uniquing. They can have
|
/// A set of files that bypass the maps and uniquing. They can have
|
||||||
/// conflicting filenames.
|
/// conflicting filenames.
|
||||||
SmallVector<std::unique_ptr<FileEntry>, 0> BypassFileEntries;
|
SmallVector<FileEntry *, 0> BypassFileEntries;
|
||||||
|
|
||||||
/// A cache that maps paths to directory entries (either real or
|
/// A cache that maps paths to directory entries (either real or
|
||||||
/// virtual) we have looked up, or an error that occurred when we looked up
|
/// virtual) we have looked up, or an error that occurred when we looked up
|
||||||
|
|
|
@ -105,10 +105,10 @@ void FileManager::addAncestorsAsVirtualDirs(StringRef Path) {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Add the virtual directory to the cache.
|
// Add the virtual directory to the cache.
|
||||||
auto UDE = std::make_unique<DirectoryEntry>();
|
auto *UDE = new (DirsAlloc.Allocate()) DirectoryEntry();
|
||||||
UDE->Name = NamedDirEnt.first();
|
UDE->Name = NamedDirEnt.first();
|
||||||
NamedDirEnt.second = *UDE.get();
|
NamedDirEnt.second = *UDE;
|
||||||
VirtualDirectoryEntries.push_back(std::move(UDE));
|
VirtualDirectoryEntries.push_back(UDE);
|
||||||
|
|
||||||
// Recursively add the other ancestors.
|
// Recursively add the other ancestors.
|
||||||
addAncestorsAsVirtualDirs(DirName);
|
addAncestorsAsVirtualDirs(DirName);
|
||||||
|
@ -172,14 +172,15 @@ FileManager::getDirectoryRef(StringRef DirName, bool CacheFailure) {
|
||||||
// same inode (this occurs on Unix-like systems when one dir is
|
// same inode (this occurs on Unix-like systems when one dir is
|
||||||
// symlinked to another, for example) or the same path (on
|
// symlinked to another, for example) or the same path (on
|
||||||
// Windows).
|
// Windows).
|
||||||
DirectoryEntry &UDE = UniqueRealDirs[Status.getUniqueID()];
|
DirectoryEntry *&UDE = UniqueRealDirs[Status.getUniqueID()];
|
||||||
|
|
||||||
NamedDirEnt.second = UDE;
|
if (!UDE) {
|
||||||
if (UDE.getName().empty()) {
|
|
||||||
// We don't have this directory yet, add it. We use the string
|
// We don't have this directory yet, add it. We use the string
|
||||||
// key from the SeenDirEntries map as the string.
|
// key from the SeenDirEntries map as the string.
|
||||||
UDE.Name = InterndDirName;
|
UDE = new (DirsAlloc.Allocate()) DirectoryEntry();
|
||||||
|
UDE->Name = InterndDirName;
|
||||||
}
|
}
|
||||||
|
NamedDirEnt.second = *UDE;
|
||||||
|
|
||||||
return DirectoryEntryRef(NamedDirEnt);
|
return DirectoryEntryRef(NamedDirEnt);
|
||||||
}
|
}
|
||||||
|
@ -268,7 +269,10 @@ FileManager::getFileRef(StringRef Filename, bool openFile, bool CacheFailure) {
|
||||||
|
|
||||||
// It exists. See if we have already opened a file with the same inode.
|
// 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.
|
// This occurs when one dir is symlinked to another, for example.
|
||||||
FileEntry &UFE = UniqueRealFiles[Status.getUniqueID()];
|
FileEntry *&UFE = UniqueRealFiles[Status.getUniqueID()];
|
||||||
|
bool ReusingEntry = UFE != nullptr;
|
||||||
|
if (!UFE)
|
||||||
|
UFE = new (FilesAlloc.Allocate()) FileEntry();
|
||||||
|
|
||||||
// FIXME: This should just check `!Status.ExposesExternalVFSPath`, but the
|
// FIXME: This should just check `!Status.ExposesExternalVFSPath`, but the
|
||||||
// else branch also ends up fixing up relative paths to be the actually
|
// else branch also ends up fixing up relative paths to be the actually
|
||||||
|
@ -276,7 +280,7 @@ FileManager::getFileRef(StringRef Filename, bool openFile, bool CacheFailure) {
|
||||||
// be relied on in some clients.
|
// be relied on in some clients.
|
||||||
if (Status.getName() == Filename) {
|
if (Status.getName() == Filename) {
|
||||||
// The name matches. Set the FileEntry.
|
// The name matches. Set the FileEntry.
|
||||||
NamedFileEnt->second = FileEntryRef::MapValue(UFE, DirInfo);
|
NamedFileEnt->second = FileEntryRef::MapValue(*UFE, DirInfo);
|
||||||
} else {
|
} else {
|
||||||
// We need a redirect. First grab the actual entry we want to return.
|
// We need a redirect. First grab the actual entry we want to return.
|
||||||
//
|
//
|
||||||
|
@ -295,11 +299,11 @@ FileManager::getFileRef(StringRef Filename, bool openFile, bool CacheFailure) {
|
||||||
// API.
|
// API.
|
||||||
auto &Redirection =
|
auto &Redirection =
|
||||||
*SeenFileEntries
|
*SeenFileEntries
|
||||||
.insert({Status.getName(), FileEntryRef::MapValue(UFE, DirInfo)})
|
.insert({Status.getName(), FileEntryRef::MapValue(*UFE, DirInfo)})
|
||||||
.first;
|
.first;
|
||||||
assert(Redirection.second->V.is<FileEntry *>() &&
|
assert(Redirection.second->V.is<FileEntry *>() &&
|
||||||
"filename redirected to a non-canonical filename?");
|
"filename redirected to a non-canonical filename?");
|
||||||
assert(Redirection.second->V.get<FileEntry *>() == &UFE &&
|
assert(Redirection.second->V.get<FileEntry *>() == UFE &&
|
||||||
"filename from getStatValue() refers to wrong file");
|
"filename from getStatValue() refers to wrong file");
|
||||||
|
|
||||||
// Cache the redirection in the previously-inserted entry, still available
|
// Cache the redirection in the previously-inserted entry, still available
|
||||||
|
@ -311,7 +315,7 @@ FileManager::getFileRef(StringRef Filename, bool openFile, bool CacheFailure) {
|
||||||
}
|
}
|
||||||
|
|
||||||
FileEntryRef ReturnedRef(*NamedFileEnt);
|
FileEntryRef ReturnedRef(*NamedFileEnt);
|
||||||
if (UFE.isValid()) { // Already have an entry with this inode, return it.
|
if (ReusingEntry) { // Already have an entry with this inode, return it.
|
||||||
|
|
||||||
// FIXME: This hack ensures that `getDir()` will use the path that was
|
// FIXME: This hack ensures that `getDir()` will use the path that was
|
||||||
// used to lookup this file, even if we found a file by different path
|
// used to lookup this file, even if we found a file by different path
|
||||||
|
@ -322,8 +326,8 @@ FileManager::getFileRef(StringRef Filename, bool openFile, bool CacheFailure) {
|
||||||
// *and* the redirection hack above is removed. The removal of the latter
|
// *and* the redirection hack above is removed. The removal of the latter
|
||||||
// is required since otherwise the ref will have the exposed external VFS
|
// is required since otherwise the ref will have the exposed external VFS
|
||||||
// path still.
|
// path still.
|
||||||
if (&DirInfo.getDirEntry() != UFE.Dir && Status.ExposesExternalVFSPath)
|
if (&DirInfo.getDirEntry() != UFE->Dir && Status.ExposesExternalVFSPath)
|
||||||
UFE.Dir = &DirInfo.getDirEntry();
|
UFE->Dir = &DirInfo.getDirEntry();
|
||||||
|
|
||||||
// Always update LastRef to the last name by which a file was accessed.
|
// 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
|
// FIXME: Neither this nor always using the first reference is correct; we
|
||||||
|
@ -332,28 +336,28 @@ FileManager::getFileRef(StringRef Filename, bool openFile, bool CacheFailure) {
|
||||||
// corresponding FileEntry.
|
// corresponding FileEntry.
|
||||||
// FIXME: LastRef should be removed from FileEntry once all clients adopt
|
// FIXME: LastRef should be removed from FileEntry once all clients adopt
|
||||||
// FileEntryRef.
|
// FileEntryRef.
|
||||||
UFE.LastRef = ReturnedRef;
|
UFE->LastRef = ReturnedRef;
|
||||||
|
|
||||||
return ReturnedRef;
|
return ReturnedRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, we don't have this file yet, add it.
|
// Otherwise, we don't have this file yet, add it.
|
||||||
UFE.LastRef = ReturnedRef;
|
UFE->LastRef = ReturnedRef;
|
||||||
UFE.Size = Status.getSize();
|
UFE->Size = Status.getSize();
|
||||||
UFE.ModTime = llvm::sys::toTimeT(Status.getLastModificationTime());
|
UFE->ModTime = llvm::sys::toTimeT(Status.getLastModificationTime());
|
||||||
UFE.Dir = &DirInfo.getDirEntry();
|
UFE->Dir = &DirInfo.getDirEntry();
|
||||||
UFE.UID = NextFileUID++;
|
UFE->UID = NextFileUID++;
|
||||||
UFE.UniqueID = Status.getUniqueID();
|
UFE->UniqueID = Status.getUniqueID();
|
||||||
UFE.IsNamedPipe = Status.getType() == llvm::sys::fs::file_type::fifo_file;
|
UFE->IsNamedPipe = Status.getType() == llvm::sys::fs::file_type::fifo_file;
|
||||||
UFE.File = std::move(F);
|
UFE->File = std::move(F);
|
||||||
UFE.IsValid = true;
|
UFE->IsValid = true;
|
||||||
|
|
||||||
if (UFE.File) {
|
if (UFE->File) {
|
||||||
if (auto PathName = UFE.File->getName())
|
if (auto PathName = UFE->File->getName())
|
||||||
fillRealPathName(&UFE, *PathName);
|
fillRealPathName(UFE, *PathName);
|
||||||
} else if (!openFile) {
|
} else if (!openFile) {
|
||||||
// We should still fill the path even if we aren't opening the file.
|
// We should still fill the path even if we aren't opening the file.
|
||||||
fillRealPathName(&UFE, InterndFileName);
|
fillRealPathName(UFE, InterndFileName);
|
||||||
}
|
}
|
||||||
return ReturnedRef;
|
return ReturnedRef;
|
||||||
}
|
}
|
||||||
|
@ -417,37 +421,41 @@ FileEntryRef FileManager::getVirtualFileRef(StringRef Filename, off_t Size,
|
||||||
llvm::vfs::Status Status;
|
llvm::vfs::Status Status;
|
||||||
const char *InterndFileName = NamedFileEnt.first().data();
|
const char *InterndFileName = NamedFileEnt.first().data();
|
||||||
if (!getStatValue(InterndFileName, Status, true, nullptr)) {
|
if (!getStatValue(InterndFileName, Status, true, nullptr)) {
|
||||||
UFE = &UniqueRealFiles[Status.getUniqueID()];
|
|
||||||
Status = llvm::vfs::Status(
|
Status = llvm::vfs::Status(
|
||||||
Status.getName(), Status.getUniqueID(),
|
Status.getName(), Status.getUniqueID(),
|
||||||
llvm::sys::toTimePoint(ModificationTime),
|
llvm::sys::toTimePoint(ModificationTime),
|
||||||
Status.getUser(), Status.getGroup(), Size,
|
Status.getUser(), Status.getGroup(), Size,
|
||||||
Status.getType(), Status.getPermissions());
|
Status.getType(), Status.getPermissions());
|
||||||
|
|
||||||
NamedFileEnt.second = FileEntryRef::MapValue(*UFE, *DirInfo);
|
auto &RealFE = UniqueRealFiles[Status.getUniqueID()];
|
||||||
|
if (RealFE) {
|
||||||
// If we had already opened this file, close it now so we don't
|
// 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
|
// leak the descriptor. We're not going to use the file
|
||||||
// descriptor anyway, since this is a virtual file.
|
// descriptor anyway, since this is a virtual file.
|
||||||
if (UFE->File)
|
if (RealFE->File)
|
||||||
UFE->closeFile();
|
RealFE->closeFile();
|
||||||
|
// If we already have an entry with this inode, return it.
|
||||||
// If we already have an entry with this inode, return it.
|
//
|
||||||
//
|
// FIXME: Surely this should add a reference by the new name, and return
|
||||||
// FIXME: Surely this should add a reference by the new name, and return
|
// it instead...
|
||||||
// it instead...
|
NamedFileEnt.second = FileEntryRef::MapValue(*RealFE, *DirInfo);
|
||||||
if (UFE->isValid())
|
|
||||||
return FileEntryRef(NamedFileEnt);
|
return FileEntryRef(NamedFileEnt);
|
||||||
|
}
|
||||||
|
// File exists, but no entry - create it.
|
||||||
|
RealFE = new (FilesAlloc.Allocate()) FileEntry();
|
||||||
|
RealFE->UniqueID = Status.getUniqueID();
|
||||||
|
RealFE->IsNamedPipe =
|
||||||
|
Status.getType() == llvm::sys::fs::file_type::fifo_file;
|
||||||
|
fillRealPathName(RealFE, Status.getName());
|
||||||
|
|
||||||
UFE->UniqueID = Status.getUniqueID();
|
UFE = RealFE;
|
||||||
UFE->IsNamedPipe = Status.getType() == llvm::sys::fs::file_type::fifo_file;
|
|
||||||
fillRealPathName(UFE, Status.getName());
|
|
||||||
} else {
|
} else {
|
||||||
VirtualFileEntries.push_back(std::make_unique<FileEntry>());
|
// File does not exist, create a virtual entry.
|
||||||
UFE = VirtualFileEntries.back().get();
|
UFE = new (FilesAlloc.Allocate()) FileEntry();
|
||||||
NamedFileEnt.second = FileEntryRef::MapValue(*UFE, *DirInfo);
|
VirtualFileEntries.push_back(UFE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NamedFileEnt.second = FileEntryRef::MapValue(*UFE, *DirInfo);
|
||||||
UFE->LastRef = FileEntryRef(NamedFileEnt);
|
UFE->LastRef = FileEntryRef(NamedFileEnt);
|
||||||
UFE->Size = Size;
|
UFE->Size = Size;
|
||||||
UFE->ModTime = ModificationTime;
|
UFE->ModTime = ModificationTime;
|
||||||
|
@ -475,16 +483,15 @@ llvm::Optional<FileEntryRef> FileManager::getBypassFile(FileEntryRef VF) {
|
||||||
return FileEntryRef(*Insertion.first);
|
return FileEntryRef(*Insertion.first);
|
||||||
|
|
||||||
// Fill in the new entry from the stat.
|
// Fill in the new entry from the stat.
|
||||||
BypassFileEntries.push_back(std::make_unique<FileEntry>());
|
FileEntry *BFE = new (FilesAlloc.Allocate()) FileEntry();
|
||||||
const FileEntry &VFE = VF.getFileEntry();
|
BypassFileEntries.push_back(BFE);
|
||||||
FileEntry &BFE = *BypassFileEntries.back();
|
Insertion.first->second = FileEntryRef::MapValue(*BFE, VF.getDir());
|
||||||
Insertion.first->second = FileEntryRef::MapValue(BFE, VF.getDir());
|
BFE->LastRef = FileEntryRef(*Insertion.first);
|
||||||
BFE.LastRef = FileEntryRef(*Insertion.first);
|
BFE->Size = Status.getSize();
|
||||||
BFE.Size = Status.getSize();
|
BFE->Dir = VF.getFileEntry().Dir;
|
||||||
BFE.Dir = VFE.Dir;
|
BFE->ModTime = llvm::sys::toTimeT(Status.getLastModificationTime());
|
||||||
BFE.ModTime = llvm::sys::toTimeT(Status.getLastModificationTime());
|
BFE->UID = NextFileUID++;
|
||||||
BFE.UID = NextFileUID++;
|
BFE->IsValid = true;
|
||||||
BFE.IsValid = true;
|
|
||||||
|
|
||||||
// Save the entry in the bypass table and return.
|
// Save the entry in the bypass table and return.
|
||||||
return FileEntryRef(*Insertion.first);
|
return FileEntryRef(*Insertion.first);
|
||||||
|
@ -601,7 +608,7 @@ FileManager::getNoncachedStatValue(StringRef Path,
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileManager::GetUniqueIDMapping(
|
void FileManager::GetUniqueIDMapping(
|
||||||
SmallVectorImpl<const FileEntry *> &UIDToFiles) const {
|
SmallVectorImpl<const FileEntry *> &UIDToFiles) const {
|
||||||
UIDToFiles.clear();
|
UIDToFiles.clear();
|
||||||
UIDToFiles.resize(NextFileUID);
|
UIDToFiles.resize(NextFileUID);
|
||||||
|
|
||||||
|
@ -618,7 +625,7 @@ void FileManager::GetUniqueIDMapping(
|
||||||
|
|
||||||
// Map virtual file entries
|
// Map virtual file entries
|
||||||
for (const auto &VFE : VirtualFileEntries)
|
for (const auto &VFE : VirtualFileEntries)
|
||||||
UIDToFiles[VFE->getUID()] = VFE.get();
|
UIDToFiles[VFE->getUID()] = VFE;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringRef FileManager::getCanonicalName(const DirectoryEntry *Dir) {
|
StringRef FileManager::getCanonicalName(const DirectoryEntry *Dir) {
|
||||||
|
|
Loading…
Reference in New Issue