[cfe-commits] r117498 - in /cfe/trunk: include/clang/AST/DeclTemplate.h lib/AST/DeclTemplate.cpp lib/Serialization/ASTReaderDecl.cpp

Douglas Gregor dgregor at apple.com
Wed Oct 27 15:21:36 PDT 2010


Author: dgregor
Date: Wed Oct 27 17:21:36 2010
New Revision: 117498

URL: http://llvm.org/viewvc/llvm-project?rev=117498&view=rev
Log:
Make AST deserialization for class template specializations lazier, by
not loading the specializations of a class template until some AST
consumer needs them.

Modified:
    cfe/trunk/include/clang/AST/DeclTemplate.h
    cfe/trunk/lib/AST/DeclTemplate.cpp
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp

Modified: cfe/trunk/include/clang/AST/DeclTemplate.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclTemplate.h?rev=117498&r1=117497&r2=117498&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclTemplate.h (original)
+++ cfe/trunk/include/clang/AST/DeclTemplate.h Wed Oct 27 17:21:36 2010
@@ -1626,6 +1626,8 @@
   /// \brief Data that is common to all of the declarations of a given
   /// class template.
   struct Common : CommonBase {
+    Common() : LazySpecializations() { }
+    
     /// \brief The class template specializations for this class
     /// template, including explicit specializations and instantiations.
     llvm::FoldingSet<ClassTemplateSpecializationDecl> Specializations;
@@ -1637,19 +1639,25 @@
 
     /// \brief The injected-class-name type for this class template.
     QualType InjectedClassNameType;
+    
+    /// \brief If non-null, points to an array of specializations (including
+    /// partial specializations) known ownly by their external declaration IDs.
+    ///
+    /// The first value in the array is the number of of specializations/
+    /// partial specializations that follow.
+    uint32_t *LazySpecializations;
   };
 
+  /// \brief Load any lazily-loaded specializations from the external source.
+  void LoadLazySpecializations();
+                            
   /// \brief Retrieve the set of specializations of this class template.
-  llvm::FoldingSet<ClassTemplateSpecializationDecl> &getSpecializations() {
-    return getCommonPtr()->Specializations;
-  }
+  llvm::FoldingSet<ClassTemplateSpecializationDecl> &getSpecializations();
 
   /// \brief Retrieve the set of partial specializations of this class
   /// template.
   llvm::FoldingSet<ClassTemplatePartialSpecializationDecl> &
-  getPartialSpecializations() {
-    return getCommonPtr()->PartialSpecializations;
-  }
+  getPartialSpecializations();
 
   ClassTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
                     TemplateParameterList *Params, NamedDecl *Decl)

Modified: cfe/trunk/lib/AST/DeclTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclTemplate.cpp?rev=117498&r1=117497&r2=117498&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclTemplate.cpp (original)
+++ cfe/trunk/lib/AST/DeclTemplate.cpp Wed Oct 27 17:21:36 2010
@@ -189,6 +189,29 @@
   return New;
 }
 
+void ClassTemplateDecl::LoadLazySpecializations() {
+  Common *CommonPtr = getCommonPtr();
+  if (CommonPtr->LazySpecializations) {
+    ASTContext &Context = getASTContext();
+    uint32_t *Specs = CommonPtr->LazySpecializations;
+    CommonPtr->LazySpecializations = 0;
+    for (uint32_t I = 0, N = *Specs++; I != N; ++I)
+      (void)Context.getExternalSource()->GetExternalDecl(Specs[I]);
+  }
+}
+
+llvm::FoldingSet<ClassTemplateSpecializationDecl> &
+ClassTemplateDecl::getSpecializations() {
+  LoadLazySpecializations();
+  return getCommonPtr()->Specializations;
+}  
+
+llvm::FoldingSet<ClassTemplatePartialSpecializationDecl> &
+ClassTemplateDecl::getPartialSpecializations() {
+  LoadLazySpecializations();
+  return getCommonPtr()->PartialSpecializations;
+}  
+
 RedeclarableTemplateDecl::CommonBase *
 ClassTemplateDecl::newCommon(ASTContext &C) {
   Common *CommonPtr = new (C) Common;

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=117498&r1=117497&r2=117498&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Wed Oct 27 17:21:36 2010
@@ -1017,18 +1017,33 @@
   VisitRedeclarableTemplateDecl(D);
 
   if (D->getPreviousDeclaration() == 0) {
-    // This ClassTemplateDecl owns a CommonPtr; read it.
-
-    // FoldingSets are filled in VisitClassTemplateSpecializationDecl.
-    unsigned size = Record[Idx++];
-    while (size--)
-      cast<ClassTemplateSpecializationDecl>(Reader.GetDecl(Record[Idx++]));
-
-    size = Record[Idx++];
-    while (size--)
-      cast<ClassTemplatePartialSpecializationDecl>(
-                                                 Reader.GetDecl(Record[Idx++]));
-
+    // This ClassTemplateDecl owns a CommonPtr; read it to keep track of all of
+    // the specializations.
+    llvm::SmallVector<serialization::DeclID, 2> SpecIDs;
+    SpecIDs.push_back(0);
+    
+    // Specializations.
+    unsigned Size = Record[Idx++];
+    SpecIDs[0] += Size;
+    SpecIDs.append(Record.begin() + Idx, Record.begin() + Idx + Size);
+    Idx += Size;
+
+    // Partial specializations.
+    Size = Record[Idx++];
+    SpecIDs[0] += Size;
+    SpecIDs.append(Record.begin() + Idx, Record.begin() + Idx + Size);
+    Idx += Size;
+
+    if (SpecIDs[0]) {
+      typedef serialization::DeclID DeclID;
+      
+      ClassTemplateDecl::Common *CommonPtr = D->getCommonPtr();
+      CommonPtr->LazySpecializations
+        = new (*Reader.getContext()) DeclID [SpecIDs.size()];
+      memcpy(CommonPtr->LazySpecializations, SpecIDs.data(), 
+             SpecIDs.size() * sizeof(DeclID));
+    }
+    
     // InjectedClassNameType is computed.
   }
 }
@@ -1071,15 +1086,15 @@
   D->TemplateArgs.init(C, TemplArgs.data(), TemplArgs.size());
   D->PointOfInstantiation = ReadSourceLocation(Record, Idx);
   D->SpecializationKind = (TemplateSpecializationKind)Record[Idx++];
-
+  
   if (D->isCanonicalDecl()) { // It's kept in the folding set.
     ClassTemplateDecl *CanonPattern
                        = cast<ClassTemplateDecl>(Reader.GetDecl(Record[Idx++]));
     if (ClassTemplatePartialSpecializationDecl *Partial
-            = dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) {
-      CanonPattern->getPartialSpecializations().InsertNode(Partial);
+                       = dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) {
+      CanonPattern->getCommonPtr()->PartialSpecializations.InsertNode(Partial);
     } else {
-      CanonPattern->getSpecializations().InsertNode(D);
+      CanonPattern->getCommonPtr()->Specializations.InsertNode(D);
     }
   }
 }





More information about the cfe-commits mailing list