diff options
Diffstat (limited to 'lib/Basic/FileManager.cpp')
| -rw-r--r-- | lib/Basic/FileManager.cpp | 114 | 
1 files changed, 82 insertions, 32 deletions
diff --git a/lib/Basic/FileManager.cpp b/lib/Basic/FileManager.cpp index ee4309de937b..434ff39e77ec 100644 --- a/lib/Basic/FileManager.cpp +++ b/lib/Basic/FileManager.cpp @@ -147,6 +147,12 @@ FileManager::FileManager()  FileManager::~FileManager() {    delete &UniqueDirs;    delete &UniqueFiles; +  for (llvm::SmallVectorImpl<FileEntry *>::iterator +         V = VirtualFileEntries.begin(), +         VEnd = VirtualFileEntries.end(); +       V != VEnd;  +       ++V) +    delete *V;  }  void FileManager::addStatCache(StatSysCallCache *statCache, bool AtBeginning) { @@ -184,6 +190,30 @@ void FileManager::removeStatCache(StatSysCallCache *statCache) {      assert(false && "Stat cache not found for removal");  } +/// \brief Retrieve the directory that the given file name resides in. +static const DirectoryEntry *getDirectoryFromFile(FileManager &FileMgr, +                                                  const char *NameStart, +                                                  const char *NameEnd) { +  // Figure out what directory it is in.   If the string contains a / in it, +  // strip off everything after it. +  // FIXME: this logic should be in sys::Path. +  const char *SlashPos = NameEnd-1; +  while (SlashPos >= NameStart && !IS_DIR_SEPARATOR_CHAR(SlashPos[0])) +    --SlashPos; +  // Ignore duplicate //'s. +  while (SlashPos > NameStart && IS_DIR_SEPARATOR_CHAR(SlashPos[-1])) +    --SlashPos; + +  if (SlashPos < NameStart) { +    // Use the current directory if file has no path component. +    const char *Name = "."; +    return FileMgr.getDirectory(Name, Name+1); +  } else if (SlashPos == NameEnd-1) +    return 0;       // If filename ends with a /, it's a directory. +  else +    return FileMgr.getDirectory(NameStart, SlashPos); +} +  /// getDirectory - Lookup, cache, and verify the specified directory.  This  /// returns null if the directory doesn't exist.  /// @@ -252,33 +282,16 @@ const FileEntry *FileManager::getFile(const char *NameStart,    // By default, initialize it to invalid.    NamedFileEnt.setValue(NON_EXISTENT_FILE); -  // Figure out what directory it is in.   If the string contains a / in it, -  // strip off everything after it. -  // FIXME: this logic should be in sys::Path. -  const char *SlashPos = NameEnd-1; -  while (SlashPos >= NameStart && !IS_DIR_SEPARATOR_CHAR(SlashPos[0])) -    --SlashPos; -  // Ignore duplicate //'s. -  while (SlashPos > NameStart && IS_DIR_SEPARATOR_CHAR(SlashPos[-1])) -    --SlashPos; - -  const DirectoryEntry *DirInfo; -  if (SlashPos < NameStart) { -    // Use the current directory if file has no path component. -    const char *Name = "."; -    DirInfo = getDirectory(Name, Name+1); -  } else if (SlashPos == NameEnd-1) -    return 0;       // If filename ends with a /, it's a directory. -  else -    DirInfo = getDirectory(NameStart, SlashPos); - -  if (DirInfo == 0)  // Directory doesn't exist, file can't exist. -    return 0;    // Get the null-terminated file name as stored as the key of the    // FileEntries map.    const char *InterndFileName = NamedFileEnt.getKeyData(); +  const DirectoryEntry *DirInfo +    = getDirectoryFromFile(*this, NameStart, NameEnd); +  if (DirInfo == 0)  // Directory doesn't exist, file can't exist. +    return 0; +    // FIXME: Use the directory info to prune this, before doing the stat syscall.    // FIXME: This will reduce the # syscalls. @@ -312,6 +325,44 @@ const FileEntry *FileManager::getFile(const char *NameStart,    return &UFE;  } +const FileEntry * +FileManager::getVirtualFile(const llvm::StringRef &Filename, +                            off_t Size, time_t ModificationTime) { +  const char *NameStart = Filename.begin(), *NameEnd = Filename.end(); + +  ++NumFileLookups; + +  // See if there is already an entry in the map. +  llvm::StringMapEntry<FileEntry *> &NamedFileEnt = +    FileEntries.GetOrCreateValue(NameStart, NameEnd); + +  // See if there is already an entry in the map. +  if (NamedFileEnt.getValue()) +    return NamedFileEnt.getValue() == NON_EXISTENT_FILE +                 ? 0 : NamedFileEnt.getValue(); + +  ++NumFileCacheMisses; + +  // By default, initialize it to invalid. +  NamedFileEnt.setValue(NON_EXISTENT_FILE); + +  const DirectoryEntry *DirInfo +    = getDirectoryFromFile(*this, NameStart, NameEnd); +  if (DirInfo == 0)  // Directory doesn't exist, file can't exist. +    return 0; + +  FileEntry *UFE = new FileEntry(); +  VirtualFileEntries.push_back(UFE); +  NamedFileEnt.setValue(UFE); + +  UFE->Name    = NamedFileEnt.getKeyData(); +  UFE->Size    = Size; +  UFE->ModTime = ModificationTime; +  UFE->Dir     = DirInfo; +  UFE->UID     = NextFileUID++; +  return UFE; +} +  void FileManager::PrintStats() const {    llvm::errs() << "\n*** File Manager Stats:\n";    llvm::errs() << UniqueFiles.size() << " files found, " @@ -327,17 +378,16 @@ void FileManager::PrintStats() const {  int MemorizeStatCalls::stat(const char *path, struct stat *buf) {    int result = StatSysCallCache::stat(path, buf); -  if (result != 0) { -    // Cache failed 'stat' results. -    struct stat empty; -    memset(&empty, 0, sizeof(empty)); -    StatCalls[path] = StatResult(result, empty); -  } -  else if (!S_ISDIR(buf->st_mode) || llvm::sys::Path(path).isAbsolute()) { -    // Cache file 'stat' results and directories with absolutely -    // paths. +  // Do not cache failed stats, it is easy to construct common inconsistent +  // situations if we do, and they are not important for PCH performance (which +  // currently only needs the stats to construct the initial FileManager +  // entries). +  if (result != 0) +    return result; + +  // Cache file 'stat' results and directories with absolutely paths. +  if (!S_ISDIR(buf->st_mode) || llvm::sys::Path(path).isAbsolute())      StatCalls[path] = StatResult(result, *buf); -  }    return result;  }  | 
