From 175c8e2e57befe2db15dd339ab5eb27d0c2b6013 Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Sat, 13 Apr 2013 01:04:01 +0000 Subject: [PATCH] Speed-up ObjCMethodDecl::getOverriddenMethods(). Use an newly introduce ASTContext::getBaseObjCCategoriesAfterInterface() which caches its results instead of re-calculating the categories multiple times. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@179436 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/ASTContext.h | 11 +++++++++- lib/AST/ASTContext.cpp | 37 ++++++++++++++++++++++++++++++++-- lib/AST/DeclObjC.cpp | 32 +++++++---------------------- 3 files changed, 52 insertions(+), 28 deletions(-) diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index d4878a99a6..6a03eefbba 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -328,6 +328,10 @@ class ASTContext : public RefCountedBase { typedef llvm::TinyPtrVector CXXMethodVector; llvm::DenseMap OverriddenMethods; + /// \brief Used to cache results from \c getBaseObjCCategoriesAfterInterface. + mutable llvm::DenseMap > CatsAfterInterface; + /// \brief Mapping from each declaration context to its corresponding lambda /// mangling context. llvm::DenseMap LambdaMangleContexts; @@ -682,7 +686,12 @@ public: void getOverriddenMethods( const NamedDecl *Method, SmallVectorImpl &Overridden) const; - + + /// \brief Returns the ObjC categories of base classes, that were declared + /// after the given interface declaration. + void getBaseObjCCategoriesAfterInterface(const ObjCInterfaceDecl *D, + SmallVectorImpl &Cats) const; + /// \brief Notify the AST context that a new import declaration has been /// parsed or implicitly created within this translation unit. void addedLocalImportDecl(ImportDecl *Import); diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 170cc0298b..8ede90dede 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -1127,8 +1127,8 @@ void ASTContext::getOverriddenMethods( assert(D); if (const CXXMethodDecl *CXXMethod = dyn_cast(D)) { - Overridden.append(CXXMethod->begin_overridden_methods(), - CXXMethod->end_overridden_methods()); + Overridden.append(overridden_methods_begin(CXXMethod), + overridden_methods_end(CXXMethod)); return; } @@ -1141,6 +1141,39 @@ void ASTContext::getOverriddenMethods( Overridden.append(OverDecls.begin(), OverDecls.end()); } +void ASTContext::getBaseObjCCategoriesAfterInterface( + const ObjCInterfaceDecl *D, + SmallVectorImpl &Cats) const { + if (!D) + return; + + typedef llvm::SmallVector VecTy; + typedef llvm::DenseMap MapTy; + + std::pair + InsertOp = CatsAfterInterface.insert(std::make_pair(D, VecTy())); + VecTy &Vec = InsertOp.first->second; + if (!InsertOp.second) { + // already in map. + Cats.append(Vec.begin(), Vec.end()); + return; + } + + SourceLocation Loc = D->getLocation(); + for (const ObjCInterfaceDecl * + Class = D->getSuperClass(); Class; Class = Class->getSuperClass()) { + for (ObjCInterfaceDecl::known_categories_iterator + CatI = Class->known_categories_begin(), + CatEnd = Class->known_categories_end(); + CatI != CatEnd; ++CatI) { + if (SourceMgr.isBeforeInTranslationUnit(Loc, CatI->getLocation())) + Vec.push_back(*CatI); + } + } + + Cats.append(Vec.begin(), Vec.end()); +} + void ASTContext::addedLocalImportDecl(ImportDecl *Import) { assert(!Import->NextLocalImport && "Import declaration already in the chain"); assert(!Import->isFromASTFile() && "Non-local import declaration"); diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index 5f5ba52947..1fe262cc0c 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -959,26 +959,6 @@ static void collectOverriddenMethodsSlow(const ObjCMethodDecl *Method, } } -static void collectOnCategoriesAfterLocation(SourceLocation Loc, - const ObjCInterfaceDecl *Class, - SourceManager &SM, - const ObjCMethodDecl *Method, - SmallVectorImpl &Methods) { - if (!Class) - return; - - for (ObjCInterfaceDecl::known_categories_iterator - Cat = Class->known_categories_begin(), - CatEnd = Class->known_categories_end(); - Cat != CatEnd; ++Cat) { - if (SM.isBeforeInTranslationUnit(Loc, Cat->getLocation())) - CollectOverriddenMethodsRecurse(*Cat, Method, Methods, true); - } - - collectOnCategoriesAfterLocation(Loc, Class->getSuperClass(), SM, - Method, Methods); -} - /// \brief Faster collection that is enabled when ObjCMethodDecl::isOverriding() /// returns false. /// You'd think that in that case there are no overrides but categories can @@ -988,7 +968,7 @@ static void collectOnCategoriesAfterLocation(SourceLocation Loc, /// further in super classes. /// Methods in an implementation can overide methods in super class's category /// but not in current class's category. But, such methods -static void collectOverriddenMethodsFast(SourceManager &SM, +static void collectOverriddenMethodsFast(ASTContext &Ctx, const ObjCMethodDecl *Method, SmallVectorImpl &Methods) { assert(!Method->isOverriding()); @@ -1001,8 +981,11 @@ static void collectOverriddenMethodsFast(SourceManager &SM, if (!Class) return; - collectOnCategoriesAfterLocation(Class->getLocation(), Class->getSuperClass(), - SM, Method, Methods); + SmallVector Cats; + Ctx.getBaseObjCCategoriesAfterInterface(Class, Cats); + for (SmallVectorImpl::iterator + I = Cats.begin(), E = Cats.end(); I != E; ++I) + CollectOverriddenMethodsRecurse(*I, Method, Methods, true); } void ObjCMethodDecl::getOverriddenMethods( @@ -1015,8 +998,7 @@ void ObjCMethodDecl::getOverriddenMethods( } if (!Method->isOverriding()) { - collectOverriddenMethodsFast(getASTContext().getSourceManager(), - Method, Overridden); + collectOverriddenMethodsFast(getASTContext(), Method, Overridden); } else { collectOverriddenMethodsSlow(Method, Overridden); assert(!Overridden.empty() && -- 2.40.0