yvvan created this revision.
yvvan added reviewers: ilya-biryukov, arphaman, erikjv.

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.


https://reviews.llvm.org/D48315

Files:
  include/clang/Frontend/ASTUnit.h
  lib/Frontend/ASTUnit.cpp

Index: lib/Frontend/ASTUnit.cpp
===================================================================
--- lib/Frontend/ASTUnit.cpp
+++ lib/Frontend/ASTUnit.cpp
@@ -400,6 +400,7 @@
   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: {
@@ -518,11 +519,15 @@
   }
 
   // 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;
 }
@@ -1430,7 +1435,7 @@
   // entities the last time we rebuilt the preamble, clear out the completion
   // cache.
   if (NewPreambleTopLevelHashValue != PreambleTopLevelHashValue) {
-    CompletionCacheTopLevelHashValue = 0;
+    ASTUnitCacheMap[MainFilePath].CompletionCacheTopLevelHashValue = 0;
     PreambleTopLevelHashValue = NewPreambleTopLevelHashValue;
   }
 
@@ -1891,11 +1896,16 @@
   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.
@@ -2077,70 +2087,72 @@
   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
@@ -2177,9 +2189,15 @@
   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();
Index: include/clang/Frontend/ASTUnit.h
===================================================================
--- include/clang/Frontend/ASTUnit.h
+++ include/clang/Frontend/ASTUnit.h
@@ -302,6 +302,9 @@
     /// 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 @@
     /// 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();
@@ -328,9 +338,9 @@
   /// Retrieve the mapping from formatted type names to unique type
   /// identifiers.
   llvm::StringMap<unsigned> &getCachedCompletionTypes() {
-    return CachedCompletionTypes; 
+    return CachedCompletionTypes;
   }
-  
+
   /// Retrieve the allocator used to cache global code completions.
   std::shared_ptr<GlobalCodeCompletionAllocator>
   getCachedCompletionAllocator() {
@@ -353,24 +363,14 @@
 
   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;
-  
+
   /// Bit used by CIndex to mark when a translation unit may be in an
   /// inconsistent state, and is not safe to free.
   unsigned UnsafeToFree : 1;
@@ -629,22 +629,22 @@
   stored_diag_iterator stored_diag_afterDriver_begin() {
     if (NumStoredDiagnosticsFromDriver > StoredDiagnostics.size())
       NumStoredDiagnosticsFromDriver = 0;
-    return StoredDiagnostics.begin() + NumStoredDiagnosticsFromDriver; 
+    return StoredDiagnostics.begin() + NumStoredDiagnosticsFromDriver;
   }
 
   using cached_completion_iterator =
       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();
+  unsigned cached_completion_size() const {
+    return ASTUnitCacheMap[getMainFileName()].CachedCompletionResults.size();
   }
 
   /// Returns an iterator range for the local preprocessing entities
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to