[cfe-commits] r111165 - in /cfe/trunk: include/clang/AST/CanonicalType.h include/clang/AST/TypeOrdering.h include/clang/Frontend/ASTUnit.h lib/Frontend/ASTUnit.cpp test/Index/complete-exprs.c

Douglas Gregor dgregor at apple.com
Mon Aug 16 11:08:11 PDT 2010


Author: dgregor
Date: Mon Aug 16 13:08:11 2010
New Revision: 111165

URL: http://llvm.org/viewvc/llvm-project?rev=111165&view=rev
Log:
When caching code completions for global declarations, keep track of
the usage type of each declaration result, then compare those types to
the preferred type of the completion. This provides parity in the
priority calculation between the code-completion results produced
directly from Sema and those cached by ASTUnit. 

For the standard Cocoa.h (+ others) example, there's a penalty of 3-4
hundredeths of a second when caching the global results (for ~31,000
results), because we need an ASTContext-agnostic representation of
types for the comparison, and therefore we use... strings. Eventually,
we'd like to implement a more efficient ASTContext-agnostic encoding
of types.


Modified:
    cfe/trunk/include/clang/AST/CanonicalType.h
    cfe/trunk/include/clang/AST/TypeOrdering.h
    cfe/trunk/include/clang/Frontend/ASTUnit.h
    cfe/trunk/lib/Frontend/ASTUnit.cpp
    cfe/trunk/test/Index/complete-exprs.c

Modified: cfe/trunk/include/clang/AST/CanonicalType.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/CanonicalType.h?rev=111165&r1=111164&r2=111165&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/CanonicalType.h (original)
+++ cfe/trunk/include/clang/AST/CanonicalType.h Mon Aug 16 13:08:11 2010
@@ -703,9 +703,9 @@
 template<typename T>
 CanQual<T> CanQual<T>::getFromOpaquePtr(void *Ptr) {
   CanQual<T> Result;
-  Result.Stored.setFromOpaqueValue(Ptr);
-  assert((!Result || Result.Stored.isCanonical())
-         && "Type is not canonical!");
+  Result.Stored = QualType::getFromOpaquePtr(Ptr);
+  assert((!Result || Result.Stored.getAsOpaquePtr() == (void*)-1 ||
+          Result.Stored.isCanonical()) && "Type is not canonical!");
   return Result;
 }
 

Modified: cfe/trunk/include/clang/AST/TypeOrdering.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TypeOrdering.h?rev=111165&r1=111164&r2=111165&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/TypeOrdering.h (original)
+++ cfe/trunk/include/clang/AST/TypeOrdering.h Mon Aug 16 13:08:11 2010
@@ -17,6 +17,7 @@
 #define LLVM_CLANG_TYPE_ORDERING_H
 
 #include "clang/AST/Type.h"
+#include "clang/AST/CanonicalType.h"
 #include <functional>
 
 namespace clang {
@@ -51,6 +52,26 @@
       return LHS == RHS;
     }
   };
+
+  template<> struct DenseMapInfo<clang::CanQualType> {
+    static inline clang::CanQualType getEmptyKey() { 
+      return clang::CanQualType(); 
+    }
+    
+    static inline clang::CanQualType getTombstoneKey() {
+      using clang::CanQualType;
+      return CanQualType::getFromOpaquePtr(reinterpret_cast<clang::Type *>(-1));
+    }
+    
+    static unsigned getHashValue(clang::CanQualType Val) {
+      return (unsigned)((uintptr_t)Val.getAsOpaquePtr()) ^
+      ((unsigned)((uintptr_t)Val.getAsOpaquePtr() >> 9));
+    }
+    
+    static bool isEqual(clang::CanQualType LHS, clang::CanQualType RHS) {
+      return LHS == RHS;
+    }
+  };
 }
 
 #endif

Modified: cfe/trunk/include/clang/Frontend/ASTUnit.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/ASTUnit.h?rev=111165&r1=111164&r2=111165&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/ASTUnit.h (original)
+++ cfe/trunk/include/clang/Frontend/ASTUnit.h Mon Aug 16 13:08:11 2010
@@ -235,12 +235,30 @@
     
     /// \brief The simplified type class for a non-macro completion result.
     SimplifiedTypeClass TypeClass;
+    
+    /// \brief The type of a non-macro completion result, stored as a unique
+    /// integer used by the string map of cached completion types.
+    ///
+    /// This value will be zero if the type is not known, or a unique value
+    /// determined by the formatted type string. Se \c CachedCompletionTypes
+    /// for more information.
+    unsigned Type;
   };
   
+  /// \brief Retrieve the mapping from formatted type names to unique type
+  /// identifiers.
+  llvm::StringMap<unsigned> &getCachedCompletionTypes() { 
+    return CachedCompletionTypes; 
+  }
+  
 private:
   /// \brief The set of cached code-completion results.
   std::vector<CachedCodeCompletionResult> CachedCompletionResults;
   
+  /// \brief 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;
+  
   /// \brief Cache any "global" code-completion results, so that we can avoid
   /// recomputing them with each completion.
   void CacheCodeCompletionResults();

Modified: cfe/trunk/lib/Frontend/ASTUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/ASTUnit.cpp?rev=111165&r1=111164&r2=111165&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/ASTUnit.cpp (original)
+++ cfe/trunk/lib/Frontend/ASTUnit.cpp Mon Aug 16 13:08:11 2010
@@ -16,6 +16,7 @@
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/ASTConsumer.h"
 #include "clang/AST/DeclVisitor.h"
+#include "clang/AST/TypeOrdering.h"
 #include "clang/AST/StmtVisitor.h"
 #include "clang/Driver/Compilation.h"
 #include "clang/Driver/Driver.h"
@@ -182,6 +183,8 @@
   TheSema->GatherGlobalCodeCompletions(Results);
   
   // Translate global code completions into cached completions.
+  llvm::DenseMap<CanQualType, unsigned> CompletionTypes;
+  
   for (unsigned I = 0, N = Results.size(); I != N; ++I) {
     switch (Results[I].Kind) {
     case Result::RK_Declaration: {
@@ -192,13 +195,30 @@
       CachedResult.Priority = Results[I].Priority;
       CachedResult.Kind = Results[I].CursorKind;
 
+      // Keep track of the type of this completion in an ASTContext-agnostic 
+      // way.
       QualType UsageType = getDeclUsageType(*Ctx, Results[I].Declaration);
-      if (UsageType.isNull())
+      if (UsageType.isNull()) {
         CachedResult.TypeClass = STC_Void;
-      else {
-        CachedResult.TypeClass
-          = getSimplifiedTypeClass(Ctx->getCanonicalType(UsageType));
+        CachedResult.Type = 0;
+      } else {
+        CanQualType CanUsageType
+          = Ctx->getCanonicalType(UsageType.getUnqualifiedType());
+        CachedResult.TypeClass = getSimplifiedTypeClass(CanUsageType);
+
+        // Determine whether we have already seen this type. If so, we save
+        // ourselves the work of formatting the type string by using the 
+        // temporary, CanQualType-based hash table to find the associated value.
+        unsigned &TypeValue = CompletionTypes[CanUsageType];
+        if (TypeValue == 0) {
+          TypeValue = CompletionTypes.size();
+          CachedCompletionTypes[QualType(CanUsageType).getAsString()]
+            = TypeValue;
+        }
+        
+        CachedResult.Type = TypeValue;
       }
+      
       CachedCompletionResults.push_back(CachedResult);
       break;
     }
@@ -224,6 +244,7 @@
       CachedResult.Priority = Results[I].Priority;
       CachedResult.Kind = Results[I].CursorKind;
       CachedResult.TypeClass = STC_Void;
+      CachedResult.Type = 0;
       CachedCompletionResults.push_back(CachedResult);
       break;
     }
@@ -239,6 +260,7 @@
   for (unsigned I = 0, N = CachedCompletionResults.size(); I != N; ++I)
     delete CachedCompletionResults[I].Completion;
   CachedCompletionResults.clear();
+  CachedCompletionTypes.clear();
 }
 
 namespace {
@@ -1432,13 +1454,21 @@
           if (C->Kind == CXCursor_MacroDefinition) {
             Priority = getMacroUsagePriority(C->Completion->getTypedText(),
                                Context.getPreferredType()->isAnyPointerType());
-          } else {
+          } else if (C->Type) {
             CanQualType Expected
-              = S.Context.getCanonicalType(Context.getPreferredType());
+              = S.Context.getCanonicalType(
+                               Context.getPreferredType().getUnqualifiedType());
             SimplifiedTypeClass ExpectedSTC = getSimplifiedTypeClass(Expected);
             if (ExpectedSTC == C->TypeClass) {
-              // FIXME: How can we check for an exact match?
-              Priority /= CCF_SimilarTypeMatch;
+              // 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;
             }
           }
         }

Modified: cfe/trunk/test/Index/complete-exprs.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/complete-exprs.c?rev=111165&r1=111164&r2=111165&view=diff
==============================================================================
--- cfe/trunk/test/Index/complete-exprs.c (original)
+++ cfe/trunk/test/Index/complete-exprs.c Mon Aug 16 13:08:11 2010
@@ -20,10 +20,9 @@
 // CHECK-CC1: ParmDecl:{ResultType int}{TypedText j} (2)
 // CHECK-CC1: NotImplemented:{TypedText sizeof}{LeftParen (}{Placeholder expression-or-type}{RightParen )} (30)
 // RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:7:9 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC1a %s
-// FIXME: Priorities aren't right
 // CHECK-CC1a: ParmDecl:{ResultType int}{TypedText j} (2)
 // CHECK-CC1a: NotImplemented:{TypedText sizeof}{LeftParen (}{Placeholder expression-or-type}{RightParen )} (30)
-// CHECK-CC1a: FunctionDecl:{ResultType int}{TypedText f}{LeftParen (}{Placeholder int}{RightParen )} (25)
+// CHECK-CC1a: FunctionDecl:{ResultType int}{TypedText f}{LeftParen (}{Placeholder int}{RightParen )} (12)
 // CHECK-CC1a: macro definition:{TypedText __VERSION__} (70)
 // RUN: c-index-test -code-completion-at=%s:7:14 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC3 %s
 // RUN: env CINDEXTEST_EDITING=1 c-index-test -code-completion-at=%s:7:14 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC3 %s





More information about the cfe-commits mailing list