From 64c0630585ac46bc3dbeb69ada50b106df8419f1 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Thu, 22 May 2014 23:19:02 +0000 Subject: [PATCH] Avoid allocating extra memory to handle the lazy definition data pointer for CXXRecordDecls when modules is enabled. llvm-svn: 209482 --- clang/include/clang/AST/DeclCXX.h | 37 ++++++++++++++++++++++++------- clang/lib/AST/Decl.cpp | 2 +- clang/lib/AST/DeclCXX.cpp | 6 ++--- clang/lib/Serialization/ASTReaderDecl.cpp | 4 ++-- 4 files changed, 35 insertions(+), 14 deletions(-) diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 4b268d4..01af64a 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -257,10 +257,31 @@ public: TypeSourceInfo *getTypeSourceInfo() const { return BaseTypeInfo; } }; +/// \brief A lazy pointer to the definition data for a declaration. +/// FIXME: This is a little CXXRecordDecl-specific that the moment. +template class LazyDefinitionDataPtr { + llvm::PointerUnion DataOrCanonicalDecl; + + LazyDefinitionDataPtr update() { + if (Decl *Canon = DataOrCanonicalDecl.template dyn_cast()) { + if (Canon->isCanonicalDecl()) + Canon->getMostRecentDecl(); + else + // Declaration isn't canonical any more; + // update it and perform path compression. + *this = Canon->getPreviousDecl()->DefinitionData.update(); + } + return *this; + } + +public: + LazyDefinitionDataPtr(Decl *Canon) : DataOrCanonicalDecl(Canon) {} + LazyDefinitionDataPtr(T *Data) : DataOrCanonicalDecl(Data) {} + T *getNotUpdated() { return DataOrCanonicalDecl.template dyn_cast(); } + T *get() { return update().getNotUpdated(); } +}; + /// \brief Represents a C++ struct/union/class. -/// -/// FIXME: This class will disappear once we've properly taught RecordDecl -/// to deal with C++-specific things. class CXXRecordDecl : public RecordDecl { friend void TagDecl::startDefinition(); @@ -496,9 +517,9 @@ class CXXRecordDecl : public RecordDecl { CXXBaseSpecifier *getVBasesSlowCase() const; }; - typedef LazyGenerationalUpdatePtr + typedef LazyDefinitionDataPtr DefinitionDataPtr; + friend class LazyDefinitionDataPtr; mutable DefinitionDataPtr DefinitionData; @@ -558,7 +579,7 @@ class CXXRecordDecl : public RecordDecl { }; struct DefinitionData &data() const { - auto *DD = DefinitionData.get(this); + auto *DD = DefinitionData.get(); assert(DD && "queried property of class with no definition"); return *DD; } @@ -643,11 +664,11 @@ public: } CXXRecordDecl *getDefinition() const { - auto *DD = DefinitionData.get(this); + auto *DD = DefinitionData.get(); return DD ? DD->Definition : nullptr; } - bool hasDefinition() const { return DefinitionData.get(this); } + bool hasDefinition() const { return DefinitionData.get(); } static CXXRecordDecl *Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index fc15bde..a783364 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -3240,7 +3240,7 @@ void TagDecl::startDefinition() { struct CXXRecordDecl::DefinitionData *Data = new (getASTContext()) struct CXXRecordDecl::DefinitionData(D); for (auto I : redecls()) - cast(I)->DefinitionData.setNotUpdated(Data); + cast(I)->DefinitionData = Data; } } diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 1c41628..0ac8b73 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -88,7 +88,7 @@ CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, const ASTContext &C, CXXRecordDecl *PrevDecl) : RecordDecl(K, TK, C, DC, StartLoc, IdLoc, Id, PrevDecl), DefinitionData(PrevDecl ? PrevDecl->DefinitionData - : DefinitionDataPtr(C)), + : DefinitionDataPtr(this)), TemplateOrInstantiation() {} CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, TagKind TK, @@ -115,9 +115,9 @@ CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC, new (C, DC) CXXRecordDecl(CXXRecord, TTK_Class, C, DC, Loc, Loc, nullptr, nullptr); R->IsBeingDefined = true; - R->DefinitionData.setNotUpdated( + R->DefinitionData = new (C) struct LambdaDefinitionData(R, Info, Dependent, IsGeneric, - CaptureDefault)); + CaptureDefault); R->MayHaveOutOfDateDef = false; R->setImplicit(true); C.getTypeDeclType(R, /*PrevDecl=*/nullptr); diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index d900f71..0c6d858 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -1405,7 +1405,7 @@ void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D) { // that all other deserialized declarations will see it. CXXRecordDecl *Canon = D->getCanonicalDecl(); if (Canon == D) { - D->DefinitionData.setNotUpdated(DD); + D->DefinitionData = DD; D->IsCompleteDefinition = true; } else if (auto *CanonDD = Canon->DefinitionData.getNotUpdated()) { // We have already deserialized a definition of this record. This @@ -1417,7 +1417,7 @@ void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D) { D->IsCompleteDefinition = false; MergeDefinitionData(D, *DD); } else { - Canon->DefinitionData.setNotUpdated(DD); + Canon->DefinitionData = DD; D->DefinitionData = Canon->DefinitionData; D->IsCompleteDefinition = true; -- 2.7.4