From 60e7064d78f1a29cf969f255a19a9ae25e6bc128 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Wed, 19 May 2010 18:39:18 +0000 Subject: [PATCH] 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@104139 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Decl.h | 5 ++- include/clang/AST/Type.h | 95 ++++++++++++++++++++++++++-------------- lib/AST/Decl.cpp | 6 +++ lib/AST/Type.cpp | 49 ++++++++++++++------- 4 files changed, 105 insertions(+), 50 deletions(-) diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index a7c947afe6..5ac920e892 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -1807,8 +1807,9 @@ public: TypedefDecl *getTypedefForAnonDecl() const { return hasExtInfo() ? 0 : TypedefDeclOrQualifier.get(); } - void setTypedefForAnonDecl(TypedefDecl *TDD) { TypedefDeclOrQualifier = TDD; } - + + void setTypedefForAnonDecl(TypedefDecl *TDD); + NestedNameSpecifier *getQualifier() const { return hasExtInfo() ? TypedefDeclOrQualifier.get()->NNS : 0; } diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index f14b652372..c24bddb300 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -768,15 +768,25 @@ private: /// 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 @@ public: /// 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 @@ public: }; private: Kind TypeKind; + +protected: + virtual Linkage getLinkageImpl() const; + public: BuiltinType(Kind K) : Type(Builtin, QualType(), /*Dependent=*/(K == Dependent)), @@ -1082,8 +1099,6 @@ public: 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 @@ class ComplexType : public Type, public llvm::FoldingSetNode { ElementType(Element) { } friend class ASTContext; // ASTContext creates these. + +protected: + virtual Linkage getLinkageImpl() const; + public: QualType getElementType() const { return ElementType; } @@ -1111,8 +1130,6 @@ public: 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 @@ class PointerType : public Type, public llvm::FoldingSetNode { 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 @@ public: 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 @@ class BlockPointerType : public Type, public llvm::FoldingSetNode { 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 @@ public: ID.AddPointer(Pointee.getAsOpaquePtr()); } - virtual Linkage getLinkage() const; - static bool classof(const Type *T) { return T->getTypeClass() == BlockPointer; } @@ -1209,6 +1230,9 @@ protected: 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 @@ public: ID.AddBoolean(SpelledAsLValue); } - virtual Linkage getLinkage() const; - static bool classof(const Type *T) { return T->getTypeClass() == LValueReference || T->getTypeClass() == RValueReference; @@ -1290,6 +1312,10 @@ class MemberPointerType : public Type, public llvm::FoldingSetNode { 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 @@ public: ID.AddPointer(Class); } - virtual Linkage getLinkage() const; - static bool classof(const Type *T) { return T->getTypeClass() == MemberPointer; } @@ -1351,6 +1375,9 @@ protected: 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 @@ public: } 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 @@ protected: : 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 @@ public: ID.AddBoolean(isPixel); } - virtual Linkage getLinkage() const; - static bool classof(const Type *T) { return T->getTypeClass() == Vector || T->getTypeClass() == ExtVector; } @@ -1873,6 +1899,10 @@ class FunctionNoProtoType : public FunctionType, public llvm::FoldingSetNode { : 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 @@ public: ID.AddPointer(ResultType.getAsOpaquePtr()); } - virtual Linkage getLinkage() const; - static bool classof(const Type *T) { return T->getTypeClass() == FunctionNoProto; } @@ -1955,6 +1983,9 @@ class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode { 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 @@ public: 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 @@ class TagType : public Type { protected: TagType(TypeClass TC, const TagDecl *D, QualType can); + virtual Linkage getLinkageImpl() const; + public: TagDecl *getDecl() const { return decl.getPointer(); } @@ -2209,8 +2240,6 @@ public: 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 @@ protected: 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 @@ public: 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 @@ class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode { PointeeType(Pointee) {} friend class ASTContext; // ASTContext creates these. +protected: + virtual Linkage getLinkageImpl() const; + public: void Destroy(ASTContext& C); @@ -3076,8 +3109,6 @@ public: bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } - virtual Linkage getLinkage() const; - void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getPointeeType()); } diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 535bd34179..c813a47f6b 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -1469,6 +1469,12 @@ TagDecl* TagDecl::getCanonicalDecl() { return getFirstDeclaration(); } +void TagDecl::setTypedefForAnonDecl(TypedefDecl *TDD) { + TypedefDeclOrQualifier = TDD; + if (TypeForDecl) + TypeForDecl->ClearLinkageCache(); +} + void TagDecl::startDefinition() { if (TagType *TagT = const_cast(TypeForDecl->getAs())) { TagT->decl.setPointer(this); diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 5d27ba469c..a7527e7ccf 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -1163,23 +1163,40 @@ void ObjCObjectTypeImpl::Profile(llvm::FoldingSetNodeID &ID) { 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(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 @@ Linkage TagType::getLinkage() const { // 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 @@ Linkage FunctionProtoType::getLinkage() const { return L; } -Linkage ObjCObjectType::getLinkage() const { +Linkage ObjCObjectType::getLinkageImpl() const { return ExternalLinkage; } -Linkage ObjCObjectPointerType::getLinkage() const { +Linkage ObjCObjectPointerType::getLinkageImpl() const { return ExternalLinkage; } -- 2.40.0