r189627 - Be lazier when loading KeyFunctions from PCH/modules. We don't need to load

Richard Smith richard-llvm at metafoo.co.uk
Thu Aug 29 16:59:27 PDT 2013


Author: rsmith
Date: Thu Aug 29 18:59:27 2013
New Revision: 189627

URL: http://llvm.org/viewvc/llvm-project?rev=189627&view=rev
Log:
Be lazier when loading KeyFunctions from PCH/modules. We don't need to load
these in eagerly if we're not actually processing a translation unit. The added
laziness here also avoids us loading in parts of a CXXRecordDecl earlier than an
upcoming class template specialization merging patch would like.

Ideally, we should mark the vtable as used when we see a definition for the key
function, rather than having a separate pass over dynamic classes at the end of
the TU. The existing approach is pretty bad for PCH/modules, since it forcibly
loads the declarations of all key functions in all imported modules, whether or
not those key functions are defined.

Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
    cfe/trunk/test/PCH/check-deserializations.cpp

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=189627&r1=189626&r2=189627&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Thu Aug 29 18:59:27 2013
@@ -148,7 +148,7 @@ class ASTContext : public RefCountedBase
   mutable TypeInfoMap MemoizedTypeInfo;
 
   /// \brief A cache mapping from CXXRecordDecls to key functions.
-  llvm::DenseMap<const CXXRecordDecl*, const CXXMethodDecl*> KeyFunctions;
+  llvm::DenseMap<const CXXRecordDecl*, LazyDeclPtr> KeyFunctions;
   
   /// \brief Mapping from ObjCContainers to their ObjCImplementations.
   llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*> ObjCImpls;

Modified: cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayoutBuilder.cpp?rev=189627&r1=189626&r2=189627&view=diff
==============================================================================
--- cfe/trunk/lib/AST/RecordLayoutBuilder.cpp (original)
+++ cfe/trunk/lib/AST/RecordLayoutBuilder.cpp Thu Aug 29 18:59:27 2013
@@ -2438,32 +2438,31 @@ const CXXMethodDecl *ASTContext::getCurr
   assert(RD->getDefinition() && "Cannot get key function for forward decl!");
   RD = cast<CXXRecordDecl>(RD->getDefinition());
 
-  const CXXMethodDecl *&entry = KeyFunctions[RD];
-  if (!entry) {
-    entry = computeKeyFunction(*this, RD);
-  }
+  LazyDeclPtr &Entry = KeyFunctions[RD];
+  if (!Entry)
+    Entry = const_cast<CXXMethodDecl*>(computeKeyFunction(*this, RD));
 
-  return entry;
+  return cast_or_null<CXXMethodDecl>(Entry.get(getExternalSource()));
 }
 
-void ASTContext::setNonKeyFunction(const CXXMethodDecl *method) {
-  assert(method == method->getFirstDeclaration() &&
+void ASTContext::setNonKeyFunction(const CXXMethodDecl *Method) {
+  assert(Method == Method->getFirstDeclaration() &&
          "not working with method declaration from class definition");
 
   // Look up the cache entry.  Since we're working with the first
   // declaration, its parent must be the class definition, which is
   // the correct key for the KeyFunctions hash.
-  llvm::DenseMap<const CXXRecordDecl*, const CXXMethodDecl*>::iterator
-    i = KeyFunctions.find(method->getParent());
+  llvm::DenseMap<const CXXRecordDecl*, LazyDeclPtr>::iterator
+    I = KeyFunctions.find(Method->getParent());
 
   // If it's not cached, there's nothing to do.
-  if (i == KeyFunctions.end()) return;
+  if (I == KeyFunctions.end()) return;
 
   // If it is cached, check whether it's the target method, and if so,
   // remove it from the cache.
-  if (i->second == method) {
+  if (I->second.get(getExternalSource()) == Method) {
     // FIXME: remember that we did this for module / chained PCH state?
-    KeyFunctions.erase(i);
+    KeyFunctions.erase(I);
   }
 }
 

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=189627&r1=189626&r2=189627&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Thu Aug 29 18:59:27 2013
@@ -1276,11 +1276,11 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CX
   }
   }
 
-  // Load the key function to avoid deserializing every method so we can
+  // Lazily load the key function to avoid deserializing every method so we can
   // compute it.
   if (D->IsCompleteDefinition) {
-    if (CXXMethodDecl *Key = ReadDeclAs<CXXMethodDecl>(Record, Idx))
-      C.KeyFunctions[D] = Key;
+    if (DeclID KeyFn = ReadDeclID(Record, Idx))
+      C.KeyFunctions[D] = KeyFn;
   }
 
   return Redecl;

Modified: cfe/trunk/test/PCH/check-deserializations.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/check-deserializations.cpp?rev=189627&r1=189626&r2=189627&view=diff
==============================================================================
--- cfe/trunk/test/PCH/check-deserializations.cpp (original)
+++ cfe/trunk/test/PCH/check-deserializations.cpp Thu Aug 29 18:59:27 2013
@@ -1,18 +1,25 @@
-// RUN: %clang_cc1 -emit-pch -o %t %s
-// RUN: %clang_cc1 -error-on-deserialized-decl S1_method -include-pch %t -emit-llvm-only %s 
+// RUN: %clang_cc1 -emit-pch -o %t.1 %s
+// RUN: %clang_cc1 -error-on-deserialized-decl S1_keyfunc -include-pch %t.1 -emit-pch -o %t.2 %s
+// RUN: %clang_cc1 -error-on-deserialized-decl S1_method -include-pch %t.2 -emit-llvm-only %s
 
-#ifndef HEADER
-#define HEADER
+#ifndef HEADER1
+#define HEADER1
 // Header.
 
 struct S1 {
-  void S1_method(); // This should not be deserialized.
+  void S1_method();
   virtual void S1_keyfunc();
 };
 
+#elif !defined(HEADER2)
+#define HEADER2
+
+// Chained PCH.
+S1 *p;
 
 #else
-// Using the header.
+
+// Using the headers.
 
 void test(S1*) {
 }





More information about the cfe-commits mailing list