From e171601ff68e51a10ac907299190a23076eb5002 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Wed, 25 Jan 2012 00:49:42 +0000 Subject: [PATCH] Rework the external Sema source's ReadMethodPool() so that it doesn't return pre-built lists. Instead, it feeds the methods it deserializes to Sema so that Sema can unique them, which keeps the chains shorter. llvm-svn: 148889 --- .../clang/Frontend/ChainedIncludesSource.h | 2 +- clang/include/clang/Sema/ExternalSemaSource.h | 5 +- clang/include/clang/Sema/Sema.h | 5 +- clang/include/clang/Serialization/ASTReader.h | 6 +- clang/lib/Frontend/ChainedIncludesSource.cpp | 5 +- clang/lib/Sema/Sema.cpp | 5 +- clang/lib/Sema/SemaDeclObjC.cpp | 49 ++++++++------- clang/lib/Serialization/ASTReader.cpp | 62 ++++++++----------- 8 files changed, 62 insertions(+), 77 deletions(-) diff --git a/clang/include/clang/Frontend/ChainedIncludesSource.h b/clang/include/clang/Frontend/ChainedIncludesSource.h index 620dbdf40c48..a08ecb3c995f 100644 --- a/clang/include/clang/Frontend/ChainedIncludesSource.h +++ b/clang/include/clang/Frontend/ChainedIncludesSource.h @@ -66,7 +66,7 @@ protected: virtual void InitializeSema(Sema &S); virtual void ForgetSema(); - virtual std::pair ReadMethodPool(Selector Sel); + virtual void ReadMethodPool(Selector Sel); virtual bool LookupUnqualified(LookupResult &R, Scope *S); }; diff --git a/clang/include/clang/Sema/ExternalSemaSource.h b/clang/include/clang/Sema/ExternalSemaSource.h index 7b83625fa332..785bf6acd12c 100644 --- a/clang/include/clang/Sema/ExternalSemaSource.h +++ b/clang/include/clang/Sema/ExternalSemaSource.h @@ -59,10 +59,7 @@ public: /// \brief Load the contents of the global method pool for a given /// selector. - /// - /// \returns a pair of Objective-C methods lists containing the - /// instance and factory methods, respectively, with this selector. - virtual std::pair ReadMethodPool(Selector Sel); + virtual void ReadMethodPool(Selector Sel); /// \brief Load the set of namespaces that are known to the external source, /// which will be used during typo correction. diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 28ae40444c00..30f0de375f3c 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -650,7 +650,7 @@ public: /// of -Wselector. llvm::DenseMap ReferencedSelectors; - GlobalMethodPool::iterator ReadMethodPool(Selector Sel); + void ReadMethodPool(Selector Sel); /// Private Helper predicate to check for 'self'. bool isSelfExpr(Expr *RExpr); @@ -1963,6 +1963,9 @@ public: /// warns each time an exact match is found. void CheckCategoryVsClassMethodMatches(ObjCCategoryImplDecl *CatIMP); + /// \brief Add the given method to the list of globally-known methods. + void addMethodToGlobalList(ObjCMethodList *List, ObjCMethodDecl *Method); + private: /// AddMethodToGlobalPool - Add an instance or factory method to the global /// pool. See descriptoin of AddInstanceMethodToGlobalPool. diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index 6148151487e5..2f4a5eba7d30 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -1197,11 +1197,7 @@ public: /// \brief Load the contents of the global method pool for a given /// selector. - /// - /// \returns a pair of Objective-C methods lists containing the - /// instance and factory methods, respectively, with this selector. - virtual std::pair - ReadMethodPool(Selector Sel); + virtual void ReadMethodPool(Selector Sel); /// \brief Load the set of namespaces that are known to the external source, /// which will be used during typo correction. diff --git a/clang/lib/Frontend/ChainedIncludesSource.cpp b/clang/lib/Frontend/ChainedIncludesSource.cpp index 9694bc0403dd..45cf672aa8b8 100644 --- a/clang/lib/Frontend/ChainedIncludesSource.cpp +++ b/clang/lib/Frontend/ChainedIncludesSource.cpp @@ -231,9 +231,8 @@ void ChainedIncludesSource::InitializeSema(Sema &S) { void ChainedIncludesSource::ForgetSema() { return getFinalReader().ForgetSema(); } -std::pair -ChainedIncludesSource::ReadMethodPool(Selector Sel) { - return getFinalReader().ReadMethodPool(Sel); +void ChainedIncludesSource::ReadMethodPool(Selector Sel) { + getFinalReader().ReadMethodPool(Sel); } bool ChainedIncludesSource::LookupUnqualified(LookupResult &R, Scope *S) { return getFinalReader().LookupUnqualified(R, S); diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 28f90241d6e3..42c7897743d1 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -879,10 +879,7 @@ LambdaScopeInfo *Sema::getCurLambda() { // Pin this vtable to this file. ExternalSemaSource::~ExternalSemaSource() {} -std::pair -ExternalSemaSource::ReadMethodPool(Selector Sel) { - return std::pair(); -} +void ExternalSemaSource::ReadMethodPool(Selector Sel) { } void ExternalSemaSource::ReadKnownNamespaces( SmallVectorImpl &Namespaces) { diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index 02ba41546b97..432e3ddf5476 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -1931,9 +1931,7 @@ bool Sema::MatchTwoMethodDeclarations(const ObjCMethodDecl *left, return true; } -/// \brief Add the given method to the given list of globally-known methods. -static void addMethodToGlobalList(Sema &S, ObjCMethodList *List, - ObjCMethodDecl *Method) { +void Sema::addMethodToGlobalList(ObjCMethodList *List, ObjCMethodDecl *Method) { // If the list is empty, make it a singleton list. if (List->Method == 0) { List->Method = Method; @@ -1945,7 +1943,7 @@ static void addMethodToGlobalList(Sema &S, ObjCMethodList *List, // signature. ObjCMethodList *Previous = List; for (; List; Previous = List, List = List->Next) { - if (!S.MatchTwoMethodDeclarations(Method, List->Method)) + if (!MatchTwoMethodDeclarations(Method, List->Method)) continue; ObjCMethodDecl *PrevObjCMethod = List->Method; @@ -1972,33 +1970,27 @@ static void addMethodToGlobalList(Sema &S, ObjCMethodList *List, // We have a new signature for an existing method - add it. // This is extremely rare. Only 1% of Cocoa selectors are "overloaded". - ObjCMethodList *Mem = S.BumpAlloc.Allocate(); + ObjCMethodList *Mem = BumpAlloc.Allocate(); Previous->Next = new (Mem) ObjCMethodList(Method, 0); } /// \brief Read the contents of the method pool for a given selector from /// external storage. -/// -/// This routine should only be called once, when the method pool has no entry -/// for this selector. -Sema::GlobalMethodPool::iterator Sema::ReadMethodPool(Selector Sel) { +void Sema::ReadMethodPool(Selector Sel) { assert(ExternalSource && "We need an external AST source"); - assert(MethodPool.find(Sel) == MethodPool.end() && - "Selector data already loaded into the method pool"); - - // Read the method list from the external source. - GlobalMethods Methods = ExternalSource->ReadMethodPool(Sel); - - return MethodPool.insert(std::make_pair(Sel, Methods)).first; + ExternalSource->ReadMethodPool(Sel); } void Sema::AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl, bool instance) { GlobalMethodPool::iterator Pos = MethodPool.find(Method->getSelector()); if (Pos == MethodPool.end()) { - if (ExternalSource) - Pos = ReadMethodPool(Method->getSelector()); - else + if (ExternalSource) { + ReadMethodPool(Method->getSelector()); + Pos = MethodPool.find(Method->getSelector()); + } + + if (Pos == MethodPool.end()) Pos = MethodPool.insert(std::make_pair(Method->getSelector(), GlobalMethods())).first; } @@ -2006,7 +1998,7 @@ void Sema::AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl, Method->setDefined(impl); ObjCMethodList &Entry = instance ? Pos->second.first : Pos->second.second; - addMethodToGlobalList(*this, &Entry, Method); + addMethodToGlobalList(&Entry, Method); } /// Determines if this is an "acceptable" loose mismatch in the global @@ -2033,9 +2025,14 @@ ObjCMethodDecl *Sema::LookupMethodInGlobalPool(Selector Sel, SourceRange R, bool warn, bool instance) { GlobalMethodPool::iterator Pos = MethodPool.find(Sel); if (Pos == MethodPool.end()) { - if (ExternalSource) - Pos = ReadMethodPool(Sel); - else + if (ExternalSource) { + ReadMethodPool(Sel); + + Pos = MethodPool.find(Sel); + if (Pos == MethodPool.end()) + return 0; + + } else return 0; } @@ -2497,7 +2494,11 @@ public: Sema::GlobalMethodPool::iterator it = S.MethodPool.find(selector); if (it == S.MethodPool.end()) { if (!S.ExternalSource) return; - it = S.ReadMethodPool(selector); + S.ReadMethodPool(selector); + + it = S.MethodPool.find(selector); + if (it == S.MethodPool.end()) + return; } ObjCMethodList &list = method->isInstanceMethod() ? it->second.first : it->second.second; diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 683bc379cb99..6fa680a74f81 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -5216,30 +5216,6 @@ namespace clang { namespace serialization { llvm::SmallVector InstanceMethods; llvm::SmallVector FactoryMethods; - /// \brief Build an ObjCMethodList from a vector of Objective-C method - /// declarations. - ObjCMethodList - buildObjCMethodList(const SmallVectorImpl &Vec) const - { - ObjCMethodList List; - ObjCMethodList *Prev = 0; - for (unsigned I = 0, N = Vec.size(); I != N; ++I) { - if (!List.Method) { - // This is the first method, which is the easy case. - List.Method = Vec[I]; - Prev = &List; - continue; - } - - ObjCMethodList *Mem = - Reader.getSema()->BumpAlloc.Allocate(); - Prev->Next = new (Mem) ObjCMethodList(Vec[I], 0); - Prev = Prev->Next; - } - - return List; - } - public: ReadMethodPoolVisitor(ASTReader &Reader, Selector Sel) : Reader(Reader), Sel(Sel) { } @@ -5273,28 +5249,44 @@ namespace clang { namespace serialization { } /// \brief Retrieve the instance methods found by this visitor. - ObjCMethodList getInstanceMethods() const { - return buildObjCMethodList(InstanceMethods); + ArrayRef getInstanceMethods() const { + return InstanceMethods; } /// \brief Retrieve the instance methods found by this visitor. - ObjCMethodList getFactoryMethods() const { - return buildObjCMethodList(FactoryMethods); + ArrayRef getFactoryMethods() const { + return FactoryMethods; } }; } } // end namespace clang::serialization -std::pair -ASTReader::ReadMethodPool(Selector Sel) { +/// \brief Add the given set of methods to the method list. +static void addMethodsToPool(Sema &S, ArrayRef Methods, + ObjCMethodList &List) { + for (unsigned I = 0, N = Methods.size(); I != N; ++I) { + S.addMethodToGlobalList(&List, Methods[I]); + } +} + +void ASTReader::ReadMethodPool(Selector Sel) { ReadMethodPoolVisitor Visitor(*this, Sel); ModuleMgr.visit(&ReadMethodPoolVisitor::visit, &Visitor); - std::pair Result; - Result.first = Visitor.getInstanceMethods(); - Result.second = Visitor.getFactoryMethods(); - if (!Result.first.Method && !Result.second.Method) + if (Visitor.getInstanceMethods().empty() && + Visitor.getFactoryMethods().empty()) { ++NumMethodPoolMisses; - return Result; + return; + } + + if (!getSema()) + return; + + Sema &S = *getSema(); + Sema::GlobalMethodPool::iterator Pos + = S.MethodPool.insert(std::make_pair(Sel, Sema::GlobalMethods())).first; + + addMethodsToPool(S, Visitor.getInstanceMethods(), Pos->second.first); + addMethodsToPool(S, Visitor.getFactoryMethods(), Pos->second.second); } void ASTReader::ReadKnownNamespaces(