From eababfbddb74d186f78783a9731a78ad371c9800 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Wed, 4 Aug 2010 05:53:38 +0000 Subject: [PATCH] When we try (but fail) to build a precompiled preamble, wait for a short "cooling off" period (defaulting to 5 reparses) before trying to build a precompiled preamble again. Previously, if we failed to build the precompiled preamble at any time, we just gave up the whole charade any never tried again. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@110187 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Frontend/ASTUnit.h | 11 +++++++++ lib/Frontend/ASTUnit.cpp | 39 +++++++++++++++++++++++++------- 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h index 58f2b38707..1fd5a0ff2c 100644 --- a/include/clang/Frontend/ASTUnit.h +++ b/include/clang/Frontend/ASTUnit.h @@ -122,6 +122,17 @@ private: static const unsigned int CheckLocked = 28573289; static const unsigned int CheckUnlocked = 9803453; + /// \brief Counter that determines when we want to try building a + /// precompiled preamble. + /// + /// If zero, we will never build a precompiled preamble. Otherwise, + /// it's treated as a counter that decrements each time we reparse + /// without the benefit of a precompiled preamble. When it hits 1, + /// we'll attempt to rebuild the precompiled header. This way, if + /// building the precompiled preamble fails, we won't try again for + /// some number of calls. + unsigned PreambleRebuildCounter; + /// \brief The file in which the precompiled preamble is stored. std::string PreambleFile; diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp index c37610afc3..b553d7cd3b 100644 --- a/lib/Frontend/ASTUnit.cpp +++ b/lib/Frontend/ASTUnit.cpp @@ -40,9 +40,16 @@ #include using namespace clang; +/// \brief After failing to build a precompiled preamble (due to +/// errors in the source that occurs in the preamble), the number of +/// reparses during which we'll skip even trying to precompile the +/// preamble. +const unsigned DefaultPreambleRebuildInterval = 5; + ASTUnit::ASTUnit(bool _MainFileIsAST) : CaptureDiagnostics(false), MainFileIsAST(_MainFileIsAST), - ConcurrencyCheckValue(CheckUnlocked), SavedMainFileBuffer(0) { + ConcurrencyCheckValue(CheckUnlocked), PreambleRebuildCounter(0), + SavedMainFileBuffer(0) { } ASTUnit::~ASTUnit() { @@ -685,7 +692,9 @@ llvm::MemoryBuffer *ASTUnit::BuildPrecompiledPreamble() { } if (CreatedPreambleBuffer) delete NewPreamble.first; - + + // The next time we actually see a preamble, precompile it. + PreambleRebuildCounter = 1; return 0; } @@ -784,8 +793,17 @@ llvm::MemoryBuffer *ASTUnit::BuildPrecompiledPreamble() { // We can't reuse the previously-computed preamble. Build a new one. Preamble.clear(); llvm::sys::Path(PreambleFile).eraseFromDisk(); + PreambleRebuildCounter = 1; } - + + // If the preamble rebuild counter > 1, it's because we previously + // failed to build a preamble and we're not yet ready to try + // again. Decrement the counter and return a failure. + if (PreambleRebuildCounter > 1) { + --PreambleRebuildCounter; + return 0; + } + // We did not previously compute a preamble, or it can't be reused anyway. llvm::Timer *PreambleTimer = 0; if (TimerGroup.get()) { @@ -850,7 +868,7 @@ llvm::MemoryBuffer *ASTUnit::BuildPrecompiledPreamble() { delete NewPreamble.first; if (PreambleTimer) PreambleTimer->stopTimer(); - + PreambleRebuildCounter = DefaultPreambleRebuildInterval; return 0; } @@ -895,6 +913,7 @@ llvm::MemoryBuffer *ASTUnit::BuildPrecompiledPreamble() { delete NewPreamble.first; if (PreambleTimer) PreambleTimer->stopTimer(); + PreambleRebuildCounter = DefaultPreambleRebuildInterval; return 0; } @@ -915,6 +934,7 @@ llvm::MemoryBuffer *ASTUnit::BuildPrecompiledPreamble() { if (PreambleTimer) PreambleTimer->stopTimer(); TopLevelDeclsInPreamble.clear(); + PreambleRebuildCounter = DefaultPreambleRebuildInterval; return 0; } @@ -944,6 +964,7 @@ llvm::MemoryBuffer *ASTUnit::BuildPrecompiledPreamble() { if (PreambleTimer) PreambleTimer->stopTimer(); + PreambleRebuildCounter = 1; return CreatePaddedMainFileBuffer(NewPreamble.first, CreatedPreambleBuffer, PreambleReservedSize, @@ -1003,8 +1024,10 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI, llvm::MemoryBuffer *OverrideMainBuffer = 0; // FIXME: When C++ PCH is ready, allow use of it for a precompiled preamble. - if (PrecompilePreamble && !CI->getLangOpts().CPlusPlus) + if (PrecompilePreamble && !CI->getLangOpts().CPlusPlus) { + AST->PreambleRebuildCounter = 1; OverrideMainBuffer = AST->BuildPrecompiledPreamble(); + } llvm::Timer *ParsingTimer = 0; if (AST->TimerGroup.get()) { @@ -1110,10 +1133,10 @@ bool ASTUnit::Reparse(RemappedFile *RemappedFiles, unsigned NumRemappedFiles) { Invocation->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first, RemappedFiles[I].second); - // If we have a preamble file lying around, build or reuse the precompiled - // preamble. + // If we have a preamble file lying around, or if we might try to + // build a precompiled preamble, do so now. llvm::MemoryBuffer *OverrideMainBuffer = 0; - if (!PreambleFile.empty()) + if (!PreambleFile.empty() || PreambleRebuildCounter > 0) OverrideMainBuffer = BuildPrecompiledPreamble(); // Clear out the diagnostics state. -- 2.40.0