diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2012-12-25 00:39:58 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2012-12-25 00:39:58 +0000 |
commit | dfb316613a40d0efc033c7bd0a49da59c915fc63 (patch) | |
tree | 2667cd947b697a035beb84db61713f5681595eb9 | |
parent | a73d3db5bf38ec2c3908187c24fec7219c4e46b5 (diff) |
Cache visibility of decls.
This unifies the linkage and visibility caching. I first implemented this when
working on pr13844, but the previous fixes removed the performance advantage of
this one.
This is still a step in the right direction for making linkage and visibility
cheap to use.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@171048 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/AST/Decl.h | 10 | ||||
-rw-r--r-- | include/clang/AST/DeclBase.h | 21 | ||||
-rw-r--r-- | include/clang/AST/Type.h | 2 | ||||
-rw-r--r-- | lib/AST/Decl.cpp | 63 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaAttr.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 10 | ||||
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 12 |
8 files changed, 76 insertions, 48 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index e00779844c..bb75895df5 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -228,6 +228,12 @@ public: "Enum truncated!"); } + bool operator==(const LinkageInfo &Other) { + return linkage_ == Other.linkage_ && + visibility_ == Other.visibility_ && + explicit_ == Other.explicit_; + } + static LinkageInfo external() { return LinkageInfo(); } @@ -323,7 +329,7 @@ public: /// \brief Clear the linkage cache in response to a change /// to the declaration. - void ClearLinkageCache(); + void ClearLVCache(); /// \brief Looks through UsingDecls and ObjCCompatibleAliasDecls for /// the underlying named decl. @@ -3319,7 +3325,7 @@ void Redeclarable<decl_type>::setPreviousDeclaration(decl_type *PrevDecl) { // First one will point to this one as latest. First->RedeclLink = LatestDeclLink(static_cast<decl_type*>(this)); if (NamedDecl *ND = dyn_cast<NamedDecl>(static_cast<decl_type*>(this))) - ND->ClearLinkageCache(); + ND->ClearLVCache(); } // Inline function definitions. diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index e3fa41ef31..823340aeaf 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -241,7 +241,7 @@ private: SourceLocation Loc; /// DeclKind - This indicates which class this is. - unsigned DeclKind : 8; + unsigned DeclKind : 6; /// InvalidDecl - This indicates a semantic error occurred. unsigned InvalidDecl : 1; @@ -283,15 +283,16 @@ protected: /// IdentifierNamespace - This specifies what IDNS_* namespace this lives in. unsigned IdentifierNamespace : 12; - /// \brief Whether the \c CachedLinkage field is active. - /// - /// This field is only valid for NamedDecls subclasses. - mutable unsigned HasCachedLinkage : 1; - - /// \brief If \c HasCachedLinkage, the linkage of this declaration. + /// These fields are only valid for NamedDecls subclasses. /// - /// This field is only valid for NamedDecls subclasses. + /// \brief Nonzero if the cache (i.e. the bitfields here starting + /// with 'Cache') is valid. If so, then this is a + /// LangOptions::VisibilityMode+1. + mutable unsigned CacheValidAndVisibility : 2; + /// \brief the linkage of this declaration. mutable unsigned CachedLinkage : 2; + /// \brief true if the visibility is explicit. + mutable unsigned CachedVisibilityExplicit : 1; friend class ASTDeclWriter; friend class ASTDeclReader; @@ -308,7 +309,7 @@ protected: HasAttrs(false), Implicit(false), Used(false), Referenced(false), Access(AS_none), FromASTFile(0), Hidden(0), IdentifierNamespace(getIdentifierNamespaceForKind(DK)), - HasCachedLinkage(0) + CacheValidAndVisibility(0) { if (StatisticsEnabled) add(DK); } @@ -318,7 +319,7 @@ protected: HasAttrs(false), Implicit(false), Used(false), Referenced(false), Access(AS_none), FromASTFile(0), Hidden(0), IdentifierNamespace(getIdentifierNamespaceForKind(DK)), - HasCachedLinkage(0) + CacheValidAndVisibility(0) { if (StatisticsEnabled) add(DK); } diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index cf3b565fc3..7277f0fc68 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -1786,7 +1786,7 @@ public: std::pair<Linkage,Visibility> getLinkageAndVisibility() const; /// \brief Note that the linkage is no longer known. - void ClearLinkageCache(); + void ClearLVCache(); const char *getTypeClassName() const; diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index a2c6da67f0..a3cdb401ea 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -104,8 +104,14 @@ getLVForTemplateParameterList(const TemplateParameterList *Params) { return LV; } -/// getLVForDecl - Get the linkage and visibility for the given declaration. -static LinkageInfo getLVForDecl(const NamedDecl *D, bool OnlyTemplate); +/// Compute the linkage and visibility for the given declaration. +static LinkageInfo computeLVForDecl(const NamedDecl *D, bool OnlyTemplate); + +static LinkageInfo getLVForDecl(const NamedDecl *D, bool OnlyTemplate) { + if (!OnlyTemplate) + return D->getLinkageAndVisibility(); + return computeLVForDecl(D, OnlyTemplate); +} /// \brief Get the most restrictive linkage for the types and /// declarations in the given template argument list. @@ -569,18 +575,18 @@ static void clearLinkageForClass(const CXXRecordDecl *record) { i = record->decls_begin(), e = record->decls_end(); i != e; ++i) { Decl *child = *i; if (isa<NamedDecl>(child)) - cast<NamedDecl>(child)->ClearLinkageCache(); + cast<NamedDecl>(child)->ClearLVCache(); } } void NamedDecl::anchor() { } -void NamedDecl::ClearLinkageCache() { +void NamedDecl::ClearLVCache() { // Note that we can't skip clearing the linkage of children just // because the parent doesn't have cached linkage: we don't cache // when computing linkage for parent contexts. - HasCachedLinkage = 0; + CacheValidAndVisibility = 0; // If we're changing the linkage of a class, we need to reset the // linkage of child declarations, too. @@ -591,44 +597,44 @@ void NamedDecl::ClearLinkageCache() { dyn_cast<ClassTemplateDecl>(const_cast<NamedDecl*>(this))) { // Clear linkage for the template pattern. CXXRecordDecl *record = temp->getTemplatedDecl(); - record->HasCachedLinkage = 0; + record->CacheValidAndVisibility = 0; clearLinkageForClass(record); // We need to clear linkage for specializations, too. for (ClassTemplateDecl::spec_iterator i = temp->spec_begin(), e = temp->spec_end(); i != e; ++i) - i->ClearLinkageCache(); + i->ClearLVCache(); } // Clear cached linkage for function template decls, too. if (FunctionTemplateDecl *temp = dyn_cast<FunctionTemplateDecl>(const_cast<NamedDecl*>(this))) { - temp->getTemplatedDecl()->ClearLinkageCache(); + temp->getTemplatedDecl()->ClearLVCache(); for (FunctionTemplateDecl::spec_iterator i = temp->spec_begin(), e = temp->spec_end(); i != e; ++i) - i->ClearLinkageCache(); + i->ClearLVCache(); } } Linkage NamedDecl::getLinkage() const { - if (HasCachedLinkage) { - assert(Linkage(CachedLinkage) == - getLVForDecl(this, true).linkage()); - return Linkage(CachedLinkage); - } - - CachedLinkage = getLVForDecl(this, true).linkage(); - HasCachedLinkage = 1; - return Linkage(CachedLinkage); + return getLinkageAndVisibility().linkage(); } LinkageInfo NamedDecl::getLinkageAndVisibility() const { - LinkageInfo LI = getLVForDecl(this, false); - assert(!HasCachedLinkage || Linkage(CachedLinkage) == LI.linkage()); - HasCachedLinkage = 1; - CachedLinkage = LI.linkage(); - return LI; + if (CacheValidAndVisibility) { + Linkage L = static_cast<Linkage>(CachedLinkage); + Visibility V = static_cast<Visibility>(CacheValidAndVisibility - 1); + bool Explicit = CachedVisibilityExplicit; + LinkageInfo LV(L, V, Explicit); + assert(LV == computeLVForDecl(this, false)); + return LV; + } + LinkageInfo LV = computeLVForDecl(this, false); + CachedLinkage = LV.linkage(); + CacheValidAndVisibility = LV.visibility() + 1; + CachedVisibilityExplicit = LV.visibilityExplicit(); + return LV; } llvm::Optional<Visibility> NamedDecl::getExplicitVisibility() const { @@ -692,7 +698,7 @@ llvm::Optional<Visibility> NamedDecl::getExplicitVisibility() const { return llvm::Optional<Visibility>(); } -static LinkageInfo getLVForDecl(const NamedDecl *D, bool OnlyTemplate) { +static LinkageInfo computeLVForDecl(const NamedDecl *D, bool OnlyTemplate) { // Objective-C: treat all Objective-C declarations as having external // linkage. switch (D->getKind()) { @@ -1157,7 +1163,7 @@ VarDecl *VarDecl::CreateDeserialized(ASTContext &C, unsigned ID) { void VarDecl::setStorageClass(StorageClass SC) { assert(isLegalForVariable(SC)); if (getStorageClass() != SC) - ClearLinkageCache(); + ClearLVCache(); VarDeclBits.SClass = SC; } @@ -1653,6 +1659,7 @@ void FunctionDecl::setBody(Stmt *B) { Body = B; if (B) EndRangeLoc = B->getLocEnd(); + ClearLVCache(); } void FunctionDecl::setPure(bool P) { @@ -1757,7 +1764,7 @@ FunctionDecl *FunctionDecl::getCanonicalDecl() { void FunctionDecl::setStorageClass(StorageClass SC) { assert(isLegalForFunction(SC)); if (getStorageClass() != SC) - ClearLinkageCache(); + ClearLVCache(); SClass = SC; } @@ -2527,8 +2534,8 @@ TagDecl* TagDecl::getCanonicalDecl() { void TagDecl::setTypedefNameForAnonDecl(TypedefNameDecl *TDD) { TypedefNameDeclOrQualifier = TDD; if (TypeForDecl) - const_cast<Type*>(TypeForDecl)->ClearLinkageCache(); - ClearLinkageCache(); + const_cast<Type*>(TypeForDecl)->ClearLVCache(); + ClearLVCache(); } void TagDecl::startDefinition() { diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 26eee2d74a..673528ada0 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -2186,7 +2186,7 @@ std::pair<Linkage,Visibility> Type::getLinkageAndVisibility() const { return std::make_pair(TypeBits.getLinkage(), TypeBits.getVisibility()); } -void Type::ClearLinkageCache() { +void Type::ClearLVCache() { TypeBits.CacheValidAndVisibility = 0; if (QualType(this, 0) != CanonicalType) CanonicalType->TypeBits.CacheValidAndVisibility = 0; diff --git a/lib/Sema/SemaAttr.cpp b/lib/Sema/SemaAttr.cpp index 4406f2d956..3bfb8f22b4 100644 --- a/lib/Sema/SemaAttr.cpp +++ b/lib/Sema/SemaAttr.cpp @@ -309,7 +309,8 @@ void Sema::AddPushedVisibilityAttribute(Decl *D) { if (!VisContext) return; - if (isa<NamedDecl>(D) && cast<NamedDecl>(D)->getExplicitVisibility()) + NamedDecl *ND = dyn_cast<NamedDecl>(D); + if (ND && ND->getExplicitVisibility()) return; VisStack *Stack = static_cast<VisStack*>(VisContext); @@ -320,6 +321,7 @@ void Sema::AddPushedVisibilityAttribute(Decl *D) { = (VisibilityAttr::VisibilityType) rawType; SourceLocation loc = Stack->back().second; + ND->ClearLVCache(); D->addAttr(::new (Context) VisibilityAttr(loc, Context, type)); } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 105ef49bd8..e1d772b084 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -1775,9 +1775,13 @@ bool Sema::mergeDeclAttribute(Decl *D, InheritableAttr *Attr) { AA->getIntroduced(), AA->getDeprecated(), AA->getObsoleted(), AA->getUnavailable(), AA->getMessage()); - else if (VisibilityAttr *VA = dyn_cast<VisibilityAttr>(Attr)) + else if (VisibilityAttr *VA = dyn_cast<VisibilityAttr>(Attr)) { NewAttr = mergeVisibilityAttr(D, VA->getRange(), VA->getVisibility()); - else if (DLLImportAttr *ImportA = dyn_cast<DLLImportAttr>(Attr)) + if (NewAttr) { + NamedDecl *ND = cast<NamedDecl>(D); + ND->ClearLVCache(); + } + } else if (DLLImportAttr *ImportA = dyn_cast<DLLImportAttr>(Attr)) NewAttr = mergeDLLImportAttr(D, ImportA->getRange()); else if (DLLExportAttr *ExportA = dyn_cast<DLLExportAttr>(Attr)) NewAttr = mergeDLLExportAttr(D, ExportA->getRange()); @@ -6611,7 +6615,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, } VDecl->setTypeSourceInfo(DeducedType); VDecl->setType(DeducedType->getType()); - VDecl->ClearLinkageCache(); + VDecl->ClearLVCache(); // In ARC, infer lifetime. if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(VDecl)) diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 22aad165e9..437e2a826b 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -2147,8 +2147,11 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, Deprecated.Version, Obsoleted.Version, IsUnavailable, Str); - if (NewAttr) + if (NewAttr) { D->addAttr(NewAttr); + NamedDecl *ND = cast<NamedDecl>(D); + ND->ClearLVCache(); + } } VisibilityAttr *Sema::mergeVisibilityAttr(Decl *D, SourceRange Range, @@ -2165,6 +2168,8 @@ VisibilityAttr *Sema::mergeVisibilityAttr(Decl *D, SourceRange Range, Diag(ExistingAttr->getLocation(), diag::err_mismatched_visibility); Diag(Range.getBegin(), diag::note_previous_attribute); D->dropAttr<VisibilityAttr>(); + NamedDecl *ND = cast<NamedDecl>(D); + ND->ClearLVCache(); } return ::new (Context) VisibilityAttr(Range, Context, Vis); } @@ -2208,8 +2213,11 @@ static void handleVisibilityAttr(Sema &S, Decl *D, const AttributeList &Attr) { } VisibilityAttr *NewAttr = S.mergeVisibilityAttr(D, Attr.getRange(), type); - if (NewAttr) + if (NewAttr) { D->addAttr(NewAttr); + NamedDecl *ND = cast<NamedDecl>(D); + ND->ClearLVCache(); + } } static void handleObjCMethodFamilyAttr(Sema &S, Decl *decl, |