/// context.
void createPCHExternalASTSource(llvm::StringRef Path,
bool DisablePCHValidation,
+ bool DisableStatCache,
void *DeserializationListener);
/// Create an external AST source to read a PCH file.
static ExternalASTSource *
createPCHExternalASTSource(llvm::StringRef Path, const std::string &Sysroot,
bool DisablePCHValidation,
+ bool DisableStatCache,
Preprocessor &PP, ASTContext &Context,
void *DeserializationListener, bool Preamble);
/// precompiled headers.
bool DisablePCHValidation;
+ /// \brief When true, disables the use of the stat cache within a
+ /// precompiled header or AST file.
+ bool DisableStatCache;
+
/// \brief Dump declarations that are deserialized from PCH, for testing.
bool DumpDeserializedPCHDecls;
public:
PreprocessorOptions() : UsePredefines(true), DetailedRecord(false),
- DisablePCHValidation(false),
+ DisablePCHValidation(false), DisableStatCache(false),
DumpDeserializedPCHDecls(false),
PrecompiledPreambleBytes(0, true),
RetainRemappedFileBuffers(false) { }
/// headers when they are loaded.
bool DisableValidation;
+ /// \brief Whether to disable the use of stat caches in AST files.
+ bool DisableStatCache;
+
/// \brief Mapping from switch-case IDs in the chain to switch-case statements
///
/// Statements usually don't have IDs, but switch cases need them, so that the
/// \param DisableValidation If true, the AST reader will suppress most
/// of its regular consistency checking, allowing the use of precompiled
/// headers that cannot be determined to be compatible.
+ ///
+ /// \param DisableStatCache If true, the AST reader will ignore the
+ /// stat cache in the AST files. This performance pessimization can
+ /// help when an AST file is being used in cases where the
+ /// underlying files in the file system may have changed, but
+ /// parsing should still continue.
ASTReader(Preprocessor &PP, ASTContext *Context, const char *isysroot = 0,
- bool DisableValidation = false);
+ bool DisableValidation = false, bool DisableStatCache = false);
/// \brief Load the AST file without using any pre-initialized Preprocessor.
///
/// \param DisableValidation If true, the AST reader will suppress most
/// of its regular consistency checking, allowing the use of precompiled
/// headers that cannot be determined to be compatible.
+ ///
+ /// \param DisableStatCache If true, the AST reader will ignore the
+ /// stat cache in the AST files. This performance pessimization can
+ /// help when an AST file is being used in cases where the
+ /// underlying files in the file system may have changed, but
+ /// parsing should still continue.
ASTReader(SourceManager &SourceMgr, FileManager &FileMgr,
Diagnostic &Diags, const char *isysroot = 0,
- bool DisableValidation = false);
+ bool DisableValidation = false, bool DisableStatCache = false);
~ASTReader();
/// \brief Load the precompiled header designated by the given file
NamedFileEnt.setValue(NON_EXISTENT_FILE);
// We allow the directory to not exist. If it does exist we store it.
- //
+ FileEntry *UFE = 0;
const DirectoryEntry *DirInfo = getDirectoryFromFile(*this, Filename);
+ if (DirInfo) {
+ // Check to see if the file exists. If so, drop the virtual file
+ int FileDescriptor = -1;
+ struct stat StatBuf;
+ const char *InterndFileName = NamedFileEnt.getKeyData();
+ if (getStatValue(InterndFileName, StatBuf, &FileDescriptor) == 0) {
+ // If the stat process opened the file, close it to avoid a FD leak.
+ if (FileDescriptor != -1)
+ close(FileDescriptor);
+
+ StatBuf.st_size = Size;
+ StatBuf.st_mtime = ModificationTime;
+ UFE = &UniqueFiles.getFile(InterndFileName, StatBuf);
+
+ NamedFileEnt.setValue(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
+ // descriptor anyway, since this is a virtual file.
+ if (UFE->FD != -1) {
+ close(UFE->FD);
+ UFE->FD = -1;
+ }
+
+ // If we already have an entry with this inode, return it.
+ if (UFE->getName())
+ return UFE;
+ }
+ }
- FileEntry *UFE = new FileEntry();
- VirtualFileEntries.push_back(UFE);
- NamedFileEnt.setValue(UFE);
+ if (!UFE) {
+ UFE = new FileEntry();
+ VirtualFileEntries.push_back(UFE);
+ NamedFileEnt.setValue(UFE);
+ }
// Get the null-terminated file name as stored as the key of the
// FileEntries map.
UFE->ModTime = ModificationTime;
UFE->Dir = DirInfo;
UFE->UID = NextFileUID++;
-
- // If this virtual file resolves to a file, also map that file to the
- // newly-created file entry.
- int FileDescriptor = -1;
- struct stat StatBuf;
- if (getStatValue(InterndFileName, StatBuf, &FileDescriptor)) {
- // If the stat process opened the file, close it to avoid a FD leak.
- if (FileDescriptor != -1)
- close(FileDescriptor);
-
- return UFE;
- }
-
- UFE->FD = FileDescriptor;
- llvm::SmallString<128> FilePath(UFE->Name);
- llvm::sys::fs::make_absolute(FilePath);
- FileEntries[FilePath] = UFE;
+ UFE->FD = -1;
return UFE;
}
// Remap files.
PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts();
+ PPOpts.DisableStatCache = true;
for (PreprocessorOptions::remapped_file_buffer_iterator
R = PPOpts.remapped_file_buffer_begin(),
REnd = PPOpts.remapped_file_buffer_end();
// If the main file has been overridden due to the use of a preamble,
// make that override happen and introduce the preamble.
+ PreprocessorOpts.DisableStatCache = true;
StoredDiagnostics.insert(StoredDiagnostics.end(),
this->StoredDiagnostics.begin(),
this->StoredDiagnostics.begin() + NumStoredDiagnosticsFromDriver);
void CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path,
bool DisablePCHValidation,
+ bool DisableStatCache,
void *DeserializationListener){
llvm::OwningPtr<ExternalASTSource> Source;
bool Preamble = getPreprocessorOpts().PrecompiledPreambleBytes.first != 0;
Source.reset(createPCHExternalASTSource(Path, getHeaderSearchOpts().Sysroot,
- DisablePCHValidation,
+ DisablePCHValidation,
+ DisableStatCache,
getPreprocessor(), getASTContext(),
DeserializationListener,
Preamble));
CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path,
const std::string &Sysroot,
bool DisablePCHValidation,
+ bool DisableStatCache,
Preprocessor &PP,
ASTContext &Context,
void *DeserializationListener,
llvm::OwningPtr<ASTReader> Reader;
Reader.reset(new ASTReader(PP, &Context,
Sysroot.empty() ? 0 : Sysroot.c_str(),
- DisablePCHValidation));
+ DisablePCHValidation, DisableStatCache));
Reader->setDeserializationListener(
static_cast<ASTDeserializationListener *>(DeserializationListener));
CI.createPCHExternalASTSource(
CI.getPreprocessorOpts().ImplicitPCHInclude,
CI.getPreprocessorOpts().DisablePCHValidation,
+ CI.getPreprocessorOpts().DisableStatCache,
DeserialListener);
if (!CI.getASTContext().getExternalSource())
goto failure;
break;
}
}
- assert(!isOnlyParens &&
- "non-empty abstract-declarator contained only parens!");
}
#endif
break;
case STAT_CACHE: {
- ASTStatCache *MyStatCache =
- new ASTStatCache((const unsigned char *)BlobStart + Record[0],
- (const unsigned char *)BlobStart,
- NumStatHits, NumStatMisses);
- FileMgr.addStatCache(MyStatCache);
- F.StatCache = MyStatCache;
+ if (!DisableStatCache) {
+ ASTStatCache *MyStatCache =
+ new ASTStatCache((const unsigned char *)BlobStart + Record[0],
+ (const unsigned char *)BlobStart,
+ NumStatHits, NumStatMisses);
+ FileMgr.addStatCache(MyStatCache);
+ F.StatCache = MyStatCache;
+ }
break;
}
}
ASTReader::ASTReader(Preprocessor &PP, ASTContext *Context,
- const char *isysroot, bool DisableValidation)
+ const char *isysroot, bool DisableValidation,
+ bool DisableStatCache)
: Listener(new PCHValidator(PP, *this)), DeserializationListener(0),
SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()),
Diags(PP.getDiagnostics()), SemaObj(0), PP(&PP), Context(Context),
Consumer(0), isysroot(isysroot), DisableValidation(DisableValidation),
- NumStatHits(0), NumStatMisses(0), NumSLocEntriesRead(0),
- TotalNumSLocEntries(0), NextSLocOffset(0), NumStatementsRead(0),
- TotalNumStatements(0), NumMacrosRead(0), TotalNumMacros(0),
- NumSelectorsRead(0), NumMethodPoolEntriesRead(0), NumMethodPoolMisses(0),
- TotalNumMethodPoolEntries(0), NumLexicalDeclContextsRead(0),
- TotalLexicalDeclContexts(0), NumVisibleDeclContextsRead(0),
- TotalVisibleDeclContexts(0), NumCurrentElementsDeserializing(0) {
+ DisableStatCache(DisableStatCache), NumStatHits(0), NumStatMisses(0),
+ NumSLocEntriesRead(0), TotalNumSLocEntries(0), NextSLocOffset(0),
+ NumStatementsRead(0), TotalNumStatements(0), NumMacrosRead(0),
+ TotalNumMacros(0), NumSelectorsRead(0), NumMethodPoolEntriesRead(0),
+ NumMethodPoolMisses(0), TotalNumMethodPoolEntries(0),
+ NumLexicalDeclContextsRead(0), TotalLexicalDeclContexts(0),
+ NumVisibleDeclContextsRead(0), TotalVisibleDeclContexts(0),
+ NumCurrentElementsDeserializing(0)
+{
RelocatablePCH = false;
}
ASTReader::ASTReader(SourceManager &SourceMgr, FileManager &FileMgr,
Diagnostic &Diags, const char *isysroot,
- bool DisableValidation)
+ bool DisableValidation, bool DisableStatCache)
: DeserializationListener(0), SourceMgr(SourceMgr), FileMgr(FileMgr),
Diags(Diags), SemaObj(0), PP(0), Context(0), Consumer(0),
- isysroot(isysroot), DisableValidation(DisableValidation), NumStatHits(0),
- NumStatMisses(0), NumSLocEntriesRead(0), TotalNumSLocEntries(0),
+ isysroot(isysroot), DisableValidation(DisableValidation),
+ DisableStatCache(DisableStatCache), NumStatHits(0), NumStatMisses(0),
+ NumSLocEntriesRead(0), TotalNumSLocEntries(0),
NextSLocOffset(0), NumStatementsRead(0), TotalNumStatements(0),
NumMacrosRead(0), TotalNumMacros(0), NumSelectorsRead(0),
NumMethodPoolEntriesRead(0), NumMethodPoolMisses(0),