[cfe-commits] r104139 - in /cfe/trunk: include/clang/AST/Decl.h include/clang/AST/Type.h lib/AST/Decl.cpp lib/AST/Type.cpp

Douglas Gregor dgregor at apple.com
Wed May 19 11:39:19 PDT 2010


Author: dgregor
Date: Wed May 19 13:39:18 2010
New Revision: 104139

URL: http://llvm.org/viewvc/llvm-project?rev=104139&view=rev
Log:
Cache the linkage of a type within its canonical type, eliminating
some seriously non-linear performance with deeply nested template
instantiations, as shown in PR6998.

Modified:
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/lib/AST/Type.cpp

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=104139&r1=104138&r2=104139&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Wed May 19 13:39:18 2010
@@ -1807,8 +1807,9 @@
   TypedefDecl *getTypedefForAnonDecl() const {
     return hasExtInfo() ? 0 : TypedefDeclOrQualifier.get<TypedefDecl*>();
   }
-  void setTypedefForAnonDecl(TypedefDecl *TDD) { TypedefDeclOrQualifier = TDD; }
-
+    
+  void setTypedefForAnonDecl(TypedefDecl *TDD);
+    
   NestedNameSpecifier *getQualifier() const {
     return hasExtInfo() ? TypedefDeclOrQualifier.get<ExtInfo*>()->NNS : 0;
   }

Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=104139&r1=104138&r2=104139&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Wed May 19 13:39:18 2010
@@ -768,15 +768,25 @@
   /// Note that this should stay at the end of the ivars for Type so that
   /// subclasses can pack their bitfields into the same word.
   bool Dependent : 1;
-
+  
+  /// \brief Whether the linkage of this type is already known.
+  mutable bool LinkageKnown : 1;
+  
+  /// \brief Linkage of this type.
+  mutable unsigned CachedLinkage : 2;
+  
 protected:
-  enum { BitsRemainingInType = 23 };
+  /// \brief Compute the linkage of this type.
+  virtual Linkage getLinkageImpl() const;
+  
+  enum { BitsRemainingInType = 20 };
 
   // silence VC++ warning C4355: 'this' : used in base member initializer list
   Type *this_() { return this; }
   Type(TypeClass tc, QualType Canonical, bool dependent)
     : CanonicalType(Canonical.isNull() ? QualType(this_(), 0) : Canonical),
-      TC(tc), Dependent(dependent) {}
+      TC(tc), Dependent(dependent), LinkageKnown(false), 
+      CachedLinkage(NoLinkage) {}
   virtual ~Type() {}
   virtual void Destroy(ASTContext& C);
   friend class ASTContext;
@@ -977,10 +987,13 @@
   /// set of type specifiers.
   bool isSpecifierType() const;
 
-  const char *getTypeClassName() const;
-
   /// \brief Determine the linkage of this type.
-  virtual Linkage getLinkage() const;
+  Linkage getLinkage() const;
+  
+  /// \brief Note that the linkage is no longer known.
+  void ClearLinkageCache();
+  
+  const char *getTypeClassName() const;
 
   QualType getCanonicalTypeInternal() const {
     return CanonicalType;
@@ -1055,6 +1068,10 @@
   };
 private:
   Kind TypeKind;
+  
+protected:
+  virtual Linkage getLinkageImpl() const;
+  
 public:
   BuiltinType(Kind K)
     : Type(Builtin, QualType(), /*Dependent=*/(K == Dependent)),
@@ -1082,8 +1099,6 @@
     return TypeKind >= Float && TypeKind <= LongDouble;
   }
 
-  virtual Linkage getLinkage() const;
-
   static bool classof(const Type *T) { return T->getTypeClass() == Builtin; }
   static bool classof(const BuiltinType *) { return true; }
 };
@@ -1098,6 +1113,10 @@
     ElementType(Element) {
   }
   friend class ASTContext;  // ASTContext creates these.
+
+protected:
+  virtual Linkage getLinkageImpl() const;
+  
 public:
   QualType getElementType() const { return ElementType; }
 
@@ -1111,8 +1130,6 @@
     ID.AddPointer(Element.getAsOpaquePtr());
   }
 
-  virtual Linkage getLinkage() const;
-
   static bool classof(const Type *T) { return T->getTypeClass() == Complex; }
   static bool classof(const ComplexType *) { return true; }
 };
@@ -1126,6 +1143,10 @@
     Type(Pointer, CanonicalPtr, Pointee->isDependentType()), PointeeType(Pointee) {
   }
   friend class ASTContext;  // ASTContext creates these.
+
+protected:
+  virtual Linkage getLinkageImpl() const;
+  
 public:
 
   QualType getPointeeType() const { return PointeeType; }
@@ -1140,8 +1161,6 @@
     ID.AddPointer(Pointee.getAsOpaquePtr());
   }
 
-  virtual Linkage getLinkage() const;
-
   static bool classof(const Type *T) { return T->getTypeClass() == Pointer; }
   static bool classof(const PointerType *) { return true; }
 };
@@ -1157,6 +1176,10 @@
     PointeeType(Pointee) {
   }
   friend class ASTContext;  // ASTContext creates these.
+  
+protected:
+  virtual Linkage getLinkageImpl() const;
+  
 public:
 
   // Get the pointee type. Pointee is required to always be a function type.
@@ -1172,8 +1195,6 @@
       ID.AddPointer(Pointee.getAsOpaquePtr());
   }
 
-  virtual Linkage getLinkage() const;
-
   static bool classof(const Type *T) {
     return T->getTypeClass() == BlockPointer;
   }
@@ -1209,6 +1230,9 @@
     PointeeType(Referencee), SpelledAsLValue(SpelledAsLValue),
     InnerRef(Referencee->isReferenceType()) {
   }
+  
+  virtual Linkage getLinkageImpl() const;
+  
 public:
   bool isSpelledAsLValue() const { return SpelledAsLValue; }
   bool isInnerRef() const { return InnerRef; }
@@ -1232,8 +1256,6 @@
     ID.AddBoolean(SpelledAsLValue);
   }
 
-  virtual Linkage getLinkage() const;
-
   static bool classof(const Type *T) {
     return T->getTypeClass() == LValueReference ||
            T->getTypeClass() == RValueReference;
@@ -1290,6 +1312,10 @@
     PointeeType(Pointee), Class(Cls) {
   }
   friend class ASTContext; // ASTContext creates these.
+  
+protected:
+  virtual Linkage getLinkageImpl() const;
+  
 public:
 
   QualType getPointeeType() const { return PointeeType; }
@@ -1308,8 +1334,6 @@
     ID.AddPointer(Class);
   }
 
-  virtual Linkage getLinkage() const;
-
   static bool classof(const Type *T) {
     return T->getTypeClass() == MemberPointer;
   }
@@ -1351,6 +1375,9 @@
       ElementType(et), SizeModifier(sm), IndexTypeQuals(tq) {}
 
   friend class ASTContext;  // ASTContext creates these.
+
+  virtual Linkage getLinkageImpl() const;
+  
 public:
   QualType getElementType() const { return ElementType; }
   ArraySizeModifier getSizeModifier() const {
@@ -1361,8 +1388,6 @@
   }
   unsigned getIndexTypeCVRQualifiers() const { return IndexTypeQuals; }
 
-  virtual Linkage getLinkage() const;
-
   static bool classof(const Type *T) {
     return T->getTypeClass() == ConstantArray ||
            T->getTypeClass() == VariableArray ||
@@ -1638,6 +1663,9 @@
     : Type(tc, canonType, vecType->isDependentType()), ElementType(vecType),
       NumElements(nElements), AltiVec(isAltiVec), Pixel(isPixel) {}
   friend class ASTContext;  // ASTContext creates these.
+  
+  virtual Linkage getLinkageImpl() const;
+  
 public:
 
   QualType getElementType() const { return ElementType; }
@@ -1664,8 +1692,6 @@
     ID.AddBoolean(isPixel);
   }
 
-  virtual Linkage getLinkage() const;
-
   static bool classof(const Type *T) {
     return T->getTypeClass() == Vector || T->getTypeClass() == ExtVector;
   }
@@ -1873,6 +1899,10 @@
     : FunctionType(FunctionNoProto, Result, false, 0, Canonical,
                    /*Dependent=*/false, Info) {}
   friend class ASTContext;  // ASTContext creates these.
+  
+protected:
+  virtual Linkage getLinkageImpl() const;
+  
 public:
   // No additional state past what FunctionType provides.
 
@@ -1890,8 +1920,6 @@
     ID.AddPointer(ResultType.getAsOpaquePtr());
   }
 
-  virtual Linkage getLinkage() const;
-
   static bool classof(const Type *T) {
     return T->getTypeClass() == FunctionNoProto;
   }
@@ -1955,6 +1983,9 @@
 
   friend class ASTContext;  // ASTContext creates these.
 
+protected:
+  virtual Linkage getLinkageImpl() const;
+  
 public:
   unsigned getNumArgs() const { return NumArgs; }
   QualType getArgType(unsigned i) const {
@@ -1995,8 +2026,6 @@
   bool isSugared() const { return false; }
   QualType desugar() const { return QualType(this, 0); }
 
-  virtual Linkage getLinkage() const;
-
   static bool classof(const Type *T) {
     return T->getTypeClass() == FunctionProto;
   }
@@ -2201,6 +2230,8 @@
 protected:
   TagType(TypeClass TC, const TagDecl *D, QualType can);
 
+  virtual Linkage getLinkageImpl() const;
+  
 public:
   TagDecl *getDecl() const { return decl.getPointer(); }
 
@@ -2209,8 +2240,6 @@
   bool isBeingDefined() const { return decl.getInt(); }
   void setBeingDefined(bool Def) const { decl.setInt(Def? 1 : 0); }
 
-  virtual Linkage getLinkage() const;
-
   static bool classof(const Type *T) {
     return T->getTypeClass() >= TagFirst && T->getTypeClass() <= TagLast;
   }
@@ -2813,6 +2842,9 @@
       NumProtocols(0),
       BaseType(QualType(this_(), 0)) {}
 
+protected:
+  Linkage getLinkageImpl() const; // key function
+  
 public:
   /// getBaseType - Gets the base type of this object type.  This is
   /// always (possibly sugar for) one of:
@@ -2864,8 +2896,6 @@
   bool isSugared() const { return false; }
   QualType desugar() const { return QualType(this, 0); }
 
-  Linkage getLinkage() const; // key function
-
   static bool classof(const Type *T) {
     return T->getTypeClass() == ObjCObject ||
            T->getTypeClass() == ObjCInterface;
@@ -2974,6 +3004,9 @@
       PointeeType(Pointee) {}
   friend class ASTContext;  // ASTContext creates these.
 
+protected:
+  virtual Linkage getLinkageImpl() const;
+  
 public:
   void Destroy(ASTContext& C);
 
@@ -3076,8 +3109,6 @@
   bool isSugared() const { return false; }
   QualType desugar() const { return QualType(this, 0); }
 
-  virtual Linkage getLinkage() const;
-
   void Profile(llvm::FoldingSetNodeID &ID) {
     Profile(ID, getPointeeType());
   }

Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=104139&r1=104138&r2=104139&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Wed May 19 13:39:18 2010
@@ -1469,6 +1469,12 @@
   return getFirstDeclaration();
 }
 
+void TagDecl::setTypedefForAnonDecl(TypedefDecl *TDD) { 
+  TypedefDeclOrQualifier = TDD; 
+  if (TypeForDecl)
+    TypeForDecl->ClearLinkageCache();
+}
+
 void TagDecl::startDefinition() {
   if (TagType *TagT = const_cast<TagType *>(TypeForDecl->getAs<TagType>())) {
     TagT->decl.setPointer(this);

Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=104139&r1=104138&r2=104139&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Wed May 19 13:39:18 2010
@@ -1163,23 +1163,40 @@
   Profile(ID, getBaseType(), qual_begin(), getNumProtocols());
 }
 
-Linkage Type::getLinkage() const { 
-  // C++ [basic.link]p8:
-  //   Names not covered by these rules have no linkage.
+/// \brief Determine the linkage of this type.
+Linkage Type::getLinkage() const {
   if (this != CanonicalType.getTypePtr())
     return CanonicalType->getLinkage();
+  
+  if (!LinkageKnown) {
+    CachedLinkage = getLinkageImpl();
+    LinkageKnown = true;
+  }
+  
+  return static_cast<clang::Linkage>(CachedLinkage);
+}
 
+Linkage Type::getLinkageImpl() const { 
+  // C++ [basic.link]p8:
+  //   Names not covered by these rules have no linkage.
   return NoLinkage; 
 }
 
-Linkage BuiltinType::getLinkage() const {
+void Type::ClearLinkageCache() {
+  if (this != CanonicalType.getTypePtr())
+    CanonicalType->ClearLinkageCache();
+  else
+    LinkageKnown = false;
+}
+
+Linkage BuiltinType::getLinkageImpl() const {
   // C++ [basic.link]p8:
   //   A type is said to have linkage if and only if:
   //     - it is a fundamental type (3.9.1); or
   return ExternalLinkage;
 }
 
-Linkage TagType::getLinkage() const {
+Linkage TagType::getLinkageImpl() const {
   // C++ [basic.link]p8:
   //     - it is a class or enumeration type that is named (or has a name for
   //       linkage purposes (7.1.3)) and the name has linkage; or
@@ -1190,39 +1207,39 @@
 // C++ [basic.link]p8:
 //   - it is a compound type (3.9.2) other than a class or enumeration, 
 //     compounded exclusively from types that have linkage; or
-Linkage ComplexType::getLinkage() const {
+Linkage ComplexType::getLinkageImpl() const {
   return ElementType->getLinkage();
 }
 
-Linkage PointerType::getLinkage() const {
+Linkage PointerType::getLinkageImpl() const {
   return PointeeType->getLinkage();
 }
 
-Linkage BlockPointerType::getLinkage() const {
+Linkage BlockPointerType::getLinkageImpl() const {
   return PointeeType->getLinkage();
 }
 
-Linkage ReferenceType::getLinkage() const {
+Linkage ReferenceType::getLinkageImpl() const {
   return PointeeType->getLinkage();
 }
 
-Linkage MemberPointerType::getLinkage() const {
+Linkage MemberPointerType::getLinkageImpl() const {
   return minLinkage(Class->getLinkage(), PointeeType->getLinkage());
 }
 
-Linkage ArrayType::getLinkage() const {
+Linkage ArrayType::getLinkageImpl() const {
   return ElementType->getLinkage();
 }
 
-Linkage VectorType::getLinkage() const {
+Linkage VectorType::getLinkageImpl() const {
   return ElementType->getLinkage();
 }
 
-Linkage FunctionNoProtoType::getLinkage() const {
+Linkage FunctionNoProtoType::getLinkageImpl() const {
   return getResultType()->getLinkage();
 }
 
-Linkage FunctionProtoType::getLinkage() const {
+Linkage FunctionProtoType::getLinkageImpl() const {
   Linkage L = getResultType()->getLinkage();
   for (arg_type_iterator A = arg_type_begin(), AEnd = arg_type_end();
        A != AEnd; ++A)
@@ -1231,10 +1248,10 @@
   return L;
 }
 
-Linkage ObjCObjectType::getLinkage() const {
+Linkage ObjCObjectType::getLinkageImpl() const {
   return ExternalLinkage;
 }
 
-Linkage ObjCObjectPointerType::getLinkage() const {
+Linkage ObjCObjectPointerType::getLinkageImpl() const {
   return ExternalLinkage;
 }





More information about the cfe-commits mailing list