diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2013-04-17 00:09:08 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2013-04-17 00:09:08 +0000 |
commit | e7a77727804c12750cb39e8732e26f2a26e4ce0f (patch) | |
tree | 0495705ef5f494d3dd5e65439c3c89bd13b5f84f /lib/Sema/SemaDeclObjC.cpp | |
parent | 685d10462b875f8c056d27488c0a1b4e13ef680f (diff) |
Use the extra info in global method pool to speed up looking for ObjC overridden methods.
When we are in a implementation, we check the global method pool whether there were category
methods with the same selector. If there were none (common case) we don't need to do lookups for
overridden methods again.
Note that for an interface method (if we don't encounter its implementation), it is considered that
it overrides methods that were declared before it, not for category methods introduced after it.
This is tradeoff in favor of performance, since it is expensive to do lookups in case there was a
category, and moving the global method pool to ASTContext (so we can check it) would increase complexity.
rdar://13508196
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@179654 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDeclObjC.cpp')
-rw-r--r-- | lib/Sema/SemaDeclObjC.cpp | 44 |
1 files changed, 40 insertions, 4 deletions
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index a6f8bf7f57..0e0672c2c3 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -2809,10 +2809,46 @@ void Sema::CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod, i = overrides.begin(), e = overrides.end(); i != e; ++i) { ObjCMethodDecl *overridden = *i; - if (isa<ObjCProtocolDecl>(overridden->getDeclContext()) || - CurrentClass != overridden->getClassInterface() || - overridden->isOverriding()) - hasOverriddenMethodsInBaseOrProtocol = true; + if (!hasOverriddenMethodsInBaseOrProtocol) { + if (isa<ObjCProtocolDecl>(overridden->getDeclContext()) || + CurrentClass != overridden->getClassInterface() || + overridden->isOverriding()) { + hasOverriddenMethodsInBaseOrProtocol = true; + + } else if (isa<ObjCImplDecl>(ObjCMethod->getDeclContext())) { + // OverrideSearch will return as "overridden" the same method in the + // interface. For hasOverriddenMethodsInBaseOrProtocol, we need to + // check whether a category of a base class introduced a method with the + // same selector, after the interface method declaration. + // To avoid unnecessary lookups in the majority of cases, we use the + // extra info bits in GlobalMethodPool to check whether there were any + // category methods with this selector. + GlobalMethodPool::iterator It = + MethodPool.find(ObjCMethod->getSelector()); + if (It != MethodPool.end()) { + ObjCMethodList &List = + ObjCMethod->isInstanceMethod()? It->second.first: It->second.second; + unsigned CategCount = List.getBits(); + if (CategCount > 0) { + // If the method is in a category we'll do lookup if there were at + // least 2 category methods recorded, otherwise only one will do. + if (CategCount > 1 || + !isa<ObjCCategoryImplDecl>(overridden->getDeclContext())) { + OverrideSearch overrides(*this, overridden); + for (OverrideSearch::iterator + OI= overrides.begin(), OE= overrides.end(); OI!=OE; ++OI) { + ObjCMethodDecl *SuperOverridden = *OI; + if (CurrentClass != SuperOverridden->getClassInterface()) { + hasOverriddenMethodsInBaseOrProtocol = true; + overridden->setOverriding(true); + break; + } + } + } + } + } + } + } // Propagate down the 'related result type' bit from overridden methods. if (RTC != Sema::RTC_Incompatible && overridden->hasRelatedResultType()) |