summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIvan Donchevskii <ivan.donchevskii@qt.io>2018-06-18 14:34:13 +0200
committerIvan Donchevskii <ivan.donchevskii@qt.io>2018-10-02 06:29:52 +0000
commit9e8237e257bcff8dbf501994837cf8e7b94591e5 (patch)
tree707676c99714687560205541a3a237bf762d13a8
parentae2c4e949c91891e181caa8dac1e234062bd3a36 (diff)
[Frontend] Share global completions cache
Append ASTUnit cache with global completions cache. In case of multiple translation units for the same file reduces the memory consumption and save completions cache generation time. Here applies the same logic as for precompiled headers. This is a cherry pick from commit 43ac160b1aa4d98ad07f1e8dde5e445593dc8d91 Change-Id: I9acd8734f81f622fedd3aac08dbd45e208a70918 Reviewed-by: Nikolai Kosjar <nikolai.kosjar@qt.io>
-rw-r--r--include/clang/Frontend/ASTUnit.h26
-rw-r--r--lib/Frontend/ASTUnit.cpp154
2 files changed, 99 insertions, 81 deletions
diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h
index 412a9778bd..a58cf53943 100644
--- a/include/clang/Frontend/ASTUnit.h
+++ b/include/clang/Frontend/ASTUnit.h
@@ -302,6 +302,9 @@ public:
/// of that loading. It must be cleared when preamble is recreated.
llvm::StringMap<SourceLocation> PreambleSrcLocCache;
+ /// The set of cached code-completion results.
+ std::vector<CachedCodeCompletionResult> CachedCompletionResults;
+
/// Counter that determines when we want to try building a
/// precompiled preamble.
///
@@ -319,6 +322,13 @@ public:
/// This hash value is used to determine when we need to refresh the
/// global code-completion cache after a rebuild of the precompiled preamble.
unsigned PreambleTopLevelHashValue = 0;
+
+ /// A string hash of the top-level declaration and macro definition
+ /// names processed the last time that we reparsed the file.
+ ///
+ /// This hash value is used to determine when we need to refresh the
+ /// global code-completion cache.
+ unsigned CompletionCacheTopLevelHashValue = 0;
};
void initCache();
@@ -353,20 +363,10 @@ private:
std::unique_ptr<CodeCompletionTUInfo> CCTUInfo;
- /// The set of cached code-completion results.
- std::vector<CachedCodeCompletionResult> CachedCompletionResults;
-
/// A mapping from the formatted type name to a unique number for that
/// type, which is used for type equality comparisons.
llvm::StringMap<unsigned> CachedCompletionTypes;
- /// A string hash of the top-level declaration and macro definition
- /// names processed the last time that we reparsed the file.
- ///
- /// This hash value is used to determine when we need to refresh the
- /// global code-completion cache.
- unsigned CompletionCacheTopLevelHashValue = 0;
-
/// The current hash value for the top-level declaration and macro
/// definition names
unsigned CurrentTopLevelHashValue = 0;
@@ -636,15 +636,15 @@ public:
std::vector<CachedCodeCompletionResult>::iterator;
cached_completion_iterator cached_completion_begin() {
- return CachedCompletionResults.begin();
+ return ASTUnitCacheMap[getMainFileName()].CachedCompletionResults.begin();
}
cached_completion_iterator cached_completion_end() {
- return CachedCompletionResults.end();
+ return ASTUnitCacheMap[getMainFileName()].CachedCompletionResults.end();
}
unsigned cached_completion_size() const {
- return CachedCompletionResults.size();
+ return ASTUnitCacheMap[getMainFileName()].CachedCompletionResults.size();
}
/// Returns an iterator range for the local preprocessing entities
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index 98c428d95d..835a05a5c2 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -402,6 +402,7 @@ void ASTUnit::CacheCodeCompletionResults() {
llvm::DenseMap<CanQualType, unsigned> CompletionTypes;
CodeCompletionContext CCContext(CodeCompletionContext::CCC_TopLevel);
+ std::vector<CachedCodeCompletionResult> CachedCompletionResults;
for (auto &R : Results) {
switch (R.Kind) {
case Result::RK_Declaration: {
@@ -520,11 +521,15 @@ void ASTUnit::CacheCodeCompletionResults() {
}
// Save the current top-level hash value.
- CompletionCacheTopLevelHashValue = CurrentTopLevelHashValue;
+ StringRef MainFilePath = getMainFileName();
+ std::lock_guard<std::recursive_mutex> Lock(CacheMutex);
+ ASTUnitCacheMap[MainFilePath].CachedCompletionResults = std::move(CachedCompletionResults);
+ ASTUnitCacheMap[MainFilePath].CompletionCacheTopLevelHashValue = CurrentTopLevelHashValue;
}
void ASTUnit::ClearCachedCompletionResults() {
- CachedCompletionResults.clear();
+ std::lock_guard<std::recursive_mutex> Lock(CacheMutex);
+ ASTUnitCacheMap[getMainFileName()].CachedCompletionResults.clear();
CachedCompletionTypes.clear();
CachedCompletionAllocator = nullptr;
}
@@ -1433,7 +1438,7 @@ ASTUnit::getMainBufferWithPrecompiledPreamble(
// entities the last time we rebuilt the preamble, clear out the completion
// cache.
if (NewPreambleTopLevelHashValue != PreambleTopLevelHashValue) {
- CompletionCacheTopLevelHashValue = 0;
+ ASTUnitCacheMap[MainFilePath].CompletionCacheTopLevelHashValue = 0;
PreambleTopLevelHashValue = NewPreambleTopLevelHashValue;
}
@@ -1894,11 +1899,16 @@ bool ASTUnit::Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
bool Result =
Parse(std::move(PCHContainerOps), std::move(OverrideMainBuffer), VFS);
- // If we're caching global code-completion results, and the top-level
- // declarations have changed, clear out the code-completion cache.
- if (!Result && ShouldCacheCodeCompletionResults &&
- CurrentTopLevelHashValue != CompletionCacheTopLevelHashValue)
- CacheCodeCompletionResults();
+ {
+ std::lock_guard<std::recursive_mutex> Lock(CacheMutex);
+ // If we're caching global code-completion results, and the top-level
+ // declarations have changed, clear out the code-completion cache.
+ if (!Result && ShouldCacheCodeCompletionResults &&
+ CurrentTopLevelHashValue !=
+ ASTUnitCacheMap[MainFilePath].CompletionCacheTopLevelHashValue) {
+ CacheCodeCompletionResults();
+ }
+ }
// We now need to clear out the completion info related to this translation
// unit; it'll be recreated if necessary.
@@ -2080,70 +2090,72 @@ void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S,
llvm::StringSet<llvm::BumpPtrAllocator> HiddenNames;
using Result = CodeCompletionResult;
SmallVector<Result, 8> AllResults;
- for (ASTUnit::cached_completion_iterator
- C = AST.cached_completion_begin(),
- CEnd = AST.cached_completion_end();
- C != CEnd; ++C) {
- // If the context we are in matches any of the contexts we are
- // interested in, we'll add this result.
- if ((C->ShowInContexts & InContexts) == 0)
- continue;
- // If we haven't added any results previously, do so now.
- if (!AddedResult) {
- CalculateHiddenNames(Context, Results, NumResults, S.Context,
- HiddenNames);
- AllResults.insert(AllResults.end(), Results, Results + NumResults);
- AddedResult = true;
- }
+ {
+ std::lock_guard<std::recursive_mutex> Lock(ASTUnit::getCacheMutex());
+ for (ASTUnit::cached_completion_iterator C = AST.cached_completion_begin(),
+ CEnd = AST.cached_completion_end();
+ C != CEnd; ++C) {
+ // If the context we are in matches any of the contexts we are
+ // interested in, we'll add this result.
+ if ((C->ShowInContexts & InContexts) == 0)
+ continue;
- // Determine whether this global completion result is hidden by a local
- // completion result. If so, skip it.
- if (C->Kind != CXCursor_MacroDefinition &&
- HiddenNames.count(C->Completion->getTypedText()))
- continue;
+ // If we haven't added any results previously, do so now.
+ if (!AddedResult) {
+ CalculateHiddenNames(Context, Results, NumResults, S.Context,
+ HiddenNames);
+ AllResults.insert(AllResults.end(), Results, Results + NumResults);
+ AddedResult = true;
+ }
+
+ // Determine whether this global completion result is hidden by a local
+ // completion result. If so, skip it.
+ if (C->Kind != CXCursor_MacroDefinition &&
+ HiddenNames.count(C->Completion->getTypedText()))
+ continue;
- // Adjust priority based on similar type classes.
- unsigned Priority = C->Priority;
- CodeCompletionString *Completion = C->Completion;
- if (!Context.getPreferredType().isNull()) {
- if (C->Kind == CXCursor_MacroDefinition) {
- Priority = getMacroUsagePriority(C->Completion->getTypedText(),
- S.getLangOpts(),
- Context.getPreferredType()->isAnyPointerType());
- } else if (C->Type) {
- CanQualType Expected
- = S.Context.getCanonicalType(
- Context.getPreferredType().getUnqualifiedType());
- SimplifiedTypeClass ExpectedSTC = getSimplifiedTypeClass(Expected);
- if (ExpectedSTC == C->TypeClass) {
- // We know this type is similar; check for an exact match.
- llvm::StringMap<unsigned> &CachedCompletionTypes
- = AST.getCachedCompletionTypes();
- llvm::StringMap<unsigned>::iterator Pos
- = CachedCompletionTypes.find(QualType(Expected).getAsString());
- if (Pos != CachedCompletionTypes.end() && Pos->second == C->Type)
- Priority /= CCF_ExactTypeMatch;
- else
- Priority /= CCF_SimilarTypeMatch;
+ // Adjust priority based on similar type classes.
+ unsigned Priority = C->Priority;
+ CodeCompletionString *Completion = C->Completion;
+ if (!Context.getPreferredType().isNull()) {
+ if (C->Kind == CXCursor_MacroDefinition) {
+ Priority = getMacroUsagePriority(
+ C->Completion->getTypedText(), S.getLangOpts(),
+ Context.getPreferredType()->isAnyPointerType());
+ } else if (C->Type) {
+ CanQualType Expected = S.Context.getCanonicalType(
+ Context.getPreferredType().getUnqualifiedType());
+ SimplifiedTypeClass ExpectedSTC = getSimplifiedTypeClass(Expected);
+ if (ExpectedSTC == C->TypeClass) {
+ // We know this type is similar; check for an exact match.
+ llvm::StringMap<unsigned> &CachedCompletionTypes =
+ AST.getCachedCompletionTypes();
+ llvm::StringMap<unsigned>::iterator Pos =
+ CachedCompletionTypes.find(QualType(Expected).getAsString());
+ if (Pos != CachedCompletionTypes.end() && Pos->second == C->Type)
+ Priority /= CCF_ExactTypeMatch;
+ else
+ Priority /= CCF_SimilarTypeMatch;
+ }
}
}
- }
- // Adjust the completion string, if required.
- if (C->Kind == CXCursor_MacroDefinition &&
- Context.getKind() == CodeCompletionContext::CCC_MacroNameUse) {
- // Create a new code-completion string that just contains the
- // macro name, without its arguments.
- CodeCompletionBuilder Builder(getAllocator(), getCodeCompletionTUInfo(),
- CCP_CodePattern, C->Availability);
- Builder.AddTypedTextChunk(C->Completion->getTypedText());
- Priority = CCP_CodePattern;
- Completion = Builder.TakeString();
- }
+ // Adjust the completion string, if required.
+ if (C->Kind == CXCursor_MacroDefinition &&
+ Context.getKind() == CodeCompletionContext::CCC_MacroNameUse) {
+ // Create a new code-completion string that just contains the
+ // macro name, without its arguments.
+ CodeCompletionBuilder Builder(getAllocator(), getCodeCompletionTUInfo(),
+ CCP_CodePattern, C->Availability);
+ Builder.AddTypedTextChunk(C->Completion->getTypedText());
+ Priority = CCP_CodePattern;
+ Completion = Builder.TakeString();
+ }
- AllResults.push_back(Result(Completion, Priority, C->Kind,
- C->Availability));
+ AllResults.push_back(
+ Result(Completion, Priority, C->Kind, C->Availability));
+ }
}
// If we did not add any cached completion results, just forward the
@@ -2180,9 +2192,15 @@ void ASTUnit::CodeComplete(
PreprocessorOptions &PreprocessorOpts = CCInvocation->getPreprocessorOpts();
StringRef MainFilePath = getMainFileName();
- CodeCompleteOpts.IncludeMacros = IncludeMacros &&
- CachedCompletionResults.empty();
- CodeCompleteOpts.IncludeGlobals = CachedCompletionResults.empty();
+ {
+ std::lock_guard<std::recursive_mutex> Lock(CacheMutex);
+ CodeCompleteOpts.IncludeMacros =
+ IncludeMacros &&
+ ASTUnitCacheMap[MainFilePath].CachedCompletionResults.empty();
+ CodeCompleteOpts.IncludeGlobals =
+ ASTUnitCacheMap[MainFilePath].CachedCompletionResults.empty();
+ }
+
CodeCompleteOpts.IncludeCodePatterns = IncludeCodePatterns;
CodeCompleteOpts.IncludeBriefComments = IncludeBriefComments;
CodeCompleteOpts.LoadExternal = Consumer.loadExternal();