<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;">On Apr 12, 2013, at 6:23 PM, Jordan Rose <<a href="mailto:jordan_rose@apple.com">jordan_rose@apple.com</a>> wrote:<br><div><br class="Apple-interchange-newline"><blockquote type="cite"><div style="letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">Can you promise that you will have seen all categories by the time this is first called?<br></div></blockquote><div><br></div><div>Good point. I'll look into it..</div><br><blockquote type="cite"><div style="letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br>Jordan<br><br><br>On Apr 12, 2013, at 18:04 , Argyrios Kyrtzidis <<a href="mailto:akyrtzi@gmail.com">akyrtzi@gmail.com</a>> wrote:<br><br><blockquote type="cite">Author: akirtzidis<br>Date: Fri Apr 12 20:04:01 2013<br>New Revision: 179436<br><br>URL: <a href="http://llvm.org/viewvc/llvm-project?rev=179436&view=rev">http://llvm.org/viewvc/llvm-project?rev=179436&view=rev</a><br>Log:<br>Speed-up ObjCMethodDecl::getOverriddenMethods().<br><br>Use an newly introduce ASTContext::getBaseObjCCategoriesAfterInterface() which caches its<br>results instead of re-calculating the categories multiple times.<br><br>Modified:<br> cfe/trunk/include/clang/AST/ASTContext.h<br> cfe/trunk/lib/AST/ASTContext.cpp<br> cfe/trunk/lib/AST/DeclObjC.cpp<br><br>Modified: cfe/trunk/include/clang/AST/ASTContext.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=179436&r1=179435&r2=179436&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=179436&r1=179435&r2=179436&view=diff</a><br>==============================================================================<br>--- cfe/trunk/include/clang/AST/ASTContext.h (original)<br>+++ cfe/trunk/include/clang/AST/ASTContext.h Fri Apr 12 20:04:01 2013<br>@@ -328,6 +328,10 @@ class ASTContext : public RefCountedBase<br> typedef llvm::TinyPtrVector<const CXXMethodDecl*> CXXMethodVector;<br> llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector> OverriddenMethods;<br><br>+ /// \brief Used to cache results from \c getBaseObjCCategoriesAfterInterface.<br>+ mutable llvm::DenseMap<const ObjCInterfaceDecl *,<br>+ llvm::SmallVector<const ObjCCategoryDecl *, 2> > CatsAfterInterface;<br>+<br> /// \brief Mapping from each declaration context to its corresponding lambda<span class="Apple-converted-space"> </span><br> /// mangling context.<br> llvm::DenseMap<const DeclContext *, LambdaMangleContext> LambdaMangleContexts;<br>@@ -682,7 +686,12 @@ public:<br> void getOverriddenMethods(<br> const NamedDecl *Method,<br> SmallVectorImpl<const NamedDecl *> &Overridden) const;<br>- <br>+<br>+ /// \brief Returns the ObjC categories of base classes, that were declared<br>+ /// after the given interface declaration.<br>+ void getBaseObjCCategoriesAfterInterface(const ObjCInterfaceDecl *D,<br>+ SmallVectorImpl<const ObjCCategoryDecl *> &Cats) const;<br>+<br> /// \brief Notify the AST context that a new import declaration has been<br> /// parsed or implicitly created within this translation unit.<br> void addedLocalImportDecl(ImportDecl *Import);<br><br>Modified: cfe/trunk/lib/AST/ASTContext.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=179436&r1=179435&r2=179436&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=179436&r1=179435&r2=179436&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/AST/ASTContext.cpp (original)<br>+++ cfe/trunk/lib/AST/ASTContext.cpp Fri Apr 12 20:04:01 2013<br>@@ -1127,8 +1127,8 @@ void ASTContext::getOverriddenMethods(<br> assert(D);<br><br> if (const CXXMethodDecl *CXXMethod = dyn_cast<CXXMethodDecl>(D)) {<br>- Overridden.append(CXXMethod->begin_overridden_methods(),<br>- CXXMethod->end_overridden_methods());<br>+ Overridden.append(overridden_methods_begin(CXXMethod),<br>+ overridden_methods_end(CXXMethod));<br> return;<br> }<br><br>@@ -1141,6 +1141,39 @@ void ASTContext::getOverriddenMethods(<br> Overridden.append(OverDecls.begin(), OverDecls.end());<br>}<br><br>+void ASTContext::getBaseObjCCategoriesAfterInterface(<br>+ const ObjCInterfaceDecl *D,<br>+ SmallVectorImpl<const ObjCCategoryDecl *> &Cats) const {<br>+ if (!D)<br>+ return;<br>+ <br>+ typedef llvm::SmallVector<const ObjCCategoryDecl *, 2> VecTy;<br>+ typedef llvm::DenseMap<const ObjCInterfaceDecl *, VecTy> MapTy;<br>+ <br>+ std::pair<MapTy::iterator, bool><br>+ InsertOp = CatsAfterInterface.insert(std::make_pair(D, VecTy()));<br>+ VecTy &Vec = InsertOp.first->second;<br>+ if (!InsertOp.second) {<br>+ // already in map.<br>+ Cats.append(Vec.begin(), Vec.end());<br>+ return;<br>+ }<br>+ <br>+ SourceLocation Loc = D->getLocation();<br>+ for (const ObjCInterfaceDecl *<br>+ Class = D->getSuperClass(); Class; Class = Class->getSuperClass()) {<br>+ for (ObjCInterfaceDecl::known_categories_iterator<br>+ CatI = Class->known_categories_begin(),<br>+ CatEnd = Class->known_categories_end();<br>+ CatI != CatEnd; ++CatI) {<br>+ if (SourceMgr.isBeforeInTranslationUnit(Loc, CatI->getLocation()))<br>+ Vec.push_back(*CatI);<br>+ }<br>+ }<br>+<br>+ Cats.append(Vec.begin(), Vec.end());<br>+}<br>+<br>void ASTContext::addedLocalImportDecl(ImportDecl *Import) {<br> assert(!Import->NextLocalImport && "Import declaration already in the chain");<br> assert(!Import->isFromASTFile() && "Non-local import declaration");<br><br>Modified: cfe/trunk/lib/AST/DeclObjC.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclObjC.cpp?rev=179436&r1=179435&r2=179436&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclObjC.cpp?rev=179436&r1=179435&r2=179436&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/AST/DeclObjC.cpp (original)<br>+++ cfe/trunk/lib/AST/DeclObjC.cpp Fri Apr 12 20:04:01 2013<br>@@ -959,26 +959,6 @@ static void collectOverriddenMethodsSlow<br> }<br>}<br><br>-static void collectOnCategoriesAfterLocation(SourceLocation Loc,<br>- const ObjCInterfaceDecl *Class,<br>- SourceManager &SM,<br>- const ObjCMethodDecl *Method,<br>- SmallVectorImpl<const ObjCMethodDecl *> &Methods) {<br>- if (!Class)<br>- return;<br>-<br>- for (ObjCInterfaceDecl::known_categories_iterator<br>- Cat = Class->known_categories_begin(),<br>- CatEnd = Class->known_categories_end();<br>- Cat != CatEnd; ++Cat) {<br>- if (SM.isBeforeInTranslationUnit(Loc, Cat->getLocation()))<br>- CollectOverriddenMethodsRecurse(*Cat, Method, Methods, true);<br>- }<br>- <br>- collectOnCategoriesAfterLocation(Loc, Class->getSuperClass(), SM,<br>- Method, Methods);<br>-}<br>-<br>/// \brief Faster collection that is enabled when ObjCMethodDecl::isOverriding()<br>/// returns false.<br>/// You'd think that in that case there are no overrides but categories can<br>@@ -988,7 +968,7 @@ static void collectOnCategoriesAfterLoca<br>/// further in super classes.<br>/// Methods in an implementation can overide methods in super class's category<br>/// but not in current class's category. But, such methods<br>-static void collectOverriddenMethodsFast(SourceManager &SM,<br>+static void collectOverriddenMethodsFast(ASTContext &Ctx,<br> const ObjCMethodDecl *Method,<br> SmallVectorImpl<const ObjCMethodDecl *> &Methods) {<br> assert(!Method->isOverriding());<br>@@ -1001,8 +981,11 @@ static void collectOverriddenMethodsFast<br> if (!Class)<br> return;<br><br>- collectOnCategoriesAfterLocation(Class->getLocation(), Class->getSuperClass(),<br>- SM, Method, Methods);<br>+ SmallVector<const ObjCCategoryDecl *, 32> Cats;<br>+ Ctx.getBaseObjCCategoriesAfterInterface(Class, Cats);<br>+ for (SmallVectorImpl<const ObjCCategoryDecl *>::iterator<br>+ I = Cats.begin(), E = Cats.end(); I != E; ++I)<br>+ CollectOverriddenMethodsRecurse(*I, Method, Methods, true);<br>}<br><br>void ObjCMethodDecl::getOverriddenMethods(<br>@@ -1015,8 +998,7 @@ void ObjCMethodDecl::getOverriddenMethod<br> }<br><br> if (!Method->isOverriding()) {<br>- collectOverriddenMethodsFast(getASTContext().getSourceManager(),<br>- Method, Overridden);<br>+ collectOverriddenMethodsFast(getASTContext(), Method, Overridden);<br> } else {<br> collectOverriddenMethodsSlow(Method, Overridden);<br> assert(!Overridden.empty() &&<br><br><br>_______________________________________________<br>cfe-commits mailing list<br><a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</blockquote></div></blockquote></div><br></body></html>