forked from OSchip/llvm-project
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. llvm-svn: 171048
This commit is contained in:
parent
fe73ac34c5
commit
f92a59f0cb
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
/// These fields are only valid for NamedDecls subclasses.
|
||||
///
|
||||
/// This field is only valid for NamedDecls subclasses.
|
||||
mutable unsigned HasCachedLinkage : 1;
|
||||
|
||||
/// \brief If \c HasCachedLinkage, the linkage of this declaration.
|
||||
///
|
||||
/// 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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue