forked from OSchip/llvm-project
The semantic checking that verifies whether an Objective-C method
declared in a subclass has consistent parameter types with a method having the same selector in a superclass performs a significant number of lookups into the class hierarchy. In the example in <rdar://problem/11004361>, we spend 4.7% of -fsyntax-only time in these lookups. Optimize away most of the calls to this routine (Sema::CompareMethodParamsInBaseAndSuper) by first checking whether we have ever seen *any* method with that selector (using the global selector table). Since most selectors are unique, we can avoid the cost of this name lookup in many cases, for a 3.3% speedup. llvm-svn: 155958
This commit is contained in:
parent
cd2353402d
commit
f73e2604b1
|
@ -2130,12 +2130,15 @@ public:
|
||||||
void CheckCategoryVsClassMethodMatches(ObjCCategoryImplDecl *CatIMP);
|
void CheckCategoryVsClassMethodMatches(ObjCCategoryImplDecl *CatIMP);
|
||||||
|
|
||||||
/// \brief Add the given method to the list of globally-known methods.
|
/// \brief Add the given method to the list of globally-known methods.
|
||||||
void addMethodToGlobalList(ObjCMethodList *List, ObjCMethodDecl *Method);
|
///
|
||||||
|
/// \returns true if this is the first method in the list with the given
|
||||||
|
/// selector.
|
||||||
|
bool addMethodToGlobalList(ObjCMethodList *List, ObjCMethodDecl *Method);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// AddMethodToGlobalPool - Add an instance or factory method to the global
|
/// AddMethodToGlobalPool - Add an instance or factory method to the global
|
||||||
/// pool. See descriptoin of AddInstanceMethodToGlobalPool.
|
/// pool. See descriptoin of AddInstanceMethodToGlobalPool.
|
||||||
void AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl, bool instance);
|
bool AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl, bool instance);
|
||||||
|
|
||||||
/// LookupMethodInGlobalPool - Returns the instance or factory method and
|
/// LookupMethodInGlobalPool - Returns the instance or factory method and
|
||||||
/// optionally warns if there are multiple signatures.
|
/// optionally warns if there are multiple signatures.
|
||||||
|
@ -2148,13 +2151,17 @@ public:
|
||||||
/// unit are added to a global pool. This allows us to efficiently associate
|
/// unit are added to a global pool. This allows us to efficiently associate
|
||||||
/// a selector with a method declaraation for purposes of typechecking
|
/// a selector with a method declaraation for purposes of typechecking
|
||||||
/// messages sent to "id" (where the class of the object is unknown).
|
/// messages sent to "id" (where the class of the object is unknown).
|
||||||
void AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method, bool impl=false) {
|
///
|
||||||
AddMethodToGlobalPool(Method, impl, /*instance*/true);
|
/// Returns true if the method was added, false if a method was already there.
|
||||||
|
bool AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method, bool impl=false) {
|
||||||
|
return AddMethodToGlobalPool(Method, impl, /*instance*/true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// AddFactoryMethodToGlobalPool - Same as above, but for factory methods.
|
/// AddFactoryMethodToGlobalPool - Same as above, but for factory methods.
|
||||||
void AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method, bool impl=false) {
|
///
|
||||||
AddMethodToGlobalPool(Method, impl, /*instance*/false);
|
/// Returns true if the method was added, false if a method was already there.
|
||||||
|
bool AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method, bool impl=false) {
|
||||||
|
return AddMethodToGlobalPool(Method, impl, /*instance*/false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// AddAnyMethodToGlobalPool - Add any method, instance or factory to global
|
/// AddAnyMethodToGlobalPool - Add any method, instance or factory to global
|
||||||
|
|
|
@ -1970,12 +1970,12 @@ bool Sema::MatchTwoMethodDeclarations(const ObjCMethodDecl *left,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sema::addMethodToGlobalList(ObjCMethodList *List, ObjCMethodDecl *Method) {
|
bool Sema::addMethodToGlobalList(ObjCMethodList *List, ObjCMethodDecl *Method) {
|
||||||
// If the list is empty, make it a singleton list.
|
// If the list is empty, make it a singleton list.
|
||||||
if (List->Method == 0) {
|
if (List->Method == 0) {
|
||||||
List->Method = Method;
|
List->Method = Method;
|
||||||
List->Next = 0;
|
List->Next = 0;
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We've seen a method with this name, see if we have already seen this type
|
// We've seen a method with this name, see if we have already seen this type
|
||||||
|
@ -2004,13 +2004,14 @@ void Sema::addMethodToGlobalList(ObjCMethodList *List, ObjCMethodDecl *Method) {
|
||||||
List->Method = Method;
|
List->Method = Method;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have a new signature for an existing method - add it.
|
// We have a new signature for an existing method - add it.
|
||||||
// This is extremely rare. Only 1% of Cocoa selectors are "overloaded".
|
// This is extremely rare. Only 1% of Cocoa selectors are "overloaded".
|
||||||
ObjCMethodList *Mem = BumpAlloc.Allocate<ObjCMethodList>();
|
ObjCMethodList *Mem = BumpAlloc.Allocate<ObjCMethodList>();
|
||||||
Previous->Next = new (Mem) ObjCMethodList(Method, 0);
|
Previous->Next = new (Mem) ObjCMethodList(Method, 0);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Read the contents of the method pool for a given selector from
|
/// \brief Read the contents of the method pool for a given selector from
|
||||||
|
@ -2020,11 +2021,11 @@ void Sema::ReadMethodPool(Selector Sel) {
|
||||||
ExternalSource->ReadMethodPool(Sel);
|
ExternalSource->ReadMethodPool(Sel);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sema::AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl,
|
bool Sema::AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl,
|
||||||
bool instance) {
|
bool instance) {
|
||||||
// Ignore methods of invalid containers.
|
// Ignore methods of invalid containers.
|
||||||
if (cast<Decl>(Method->getDeclContext())->isInvalidDecl())
|
if (cast<Decl>(Method->getDeclContext())->isInvalidDecl())
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
if (ExternalSource)
|
if (ExternalSource)
|
||||||
ReadMethodPool(Method->getSelector());
|
ReadMethodPool(Method->getSelector());
|
||||||
|
@ -2037,7 +2038,7 @@ void Sema::AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl,
|
||||||
Method->setDefined(impl);
|
Method->setDefined(impl);
|
||||||
|
|
||||||
ObjCMethodList &Entry = instance ? Pos->second.first : Pos->second.second;
|
ObjCMethodList &Entry = instance ? Pos->second.first : Pos->second.second;
|
||||||
addMethodToGlobalList(&Entry, Method);
|
return addMethodToGlobalList(&Entry, Method);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determines if this is an "acceptable" loose mismatch in the global
|
/// Determines if this is an "acceptable" loose mismatch in the global
|
||||||
|
@ -2272,10 +2273,11 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd,
|
||||||
}
|
}
|
||||||
InsMap[Method->getSelector()] = Method;
|
InsMap[Method->getSelector()] = Method;
|
||||||
/// The following allows us to typecheck messages to "id".
|
/// The following allows us to typecheck messages to "id".
|
||||||
AddInstanceMethodToGlobalPool(Method);
|
if (!AddInstanceMethodToGlobalPool(Method)) {
|
||||||
// verify that the instance method conforms to the same definition of
|
// verify that the instance method conforms to the same definition of
|
||||||
// parent methods if it shadows one.
|
// parent methods if it shadows one.
|
||||||
CompareMethodParamsInBaseAndSuper(ClassDecl, Method, true);
|
CompareMethodParamsInBaseAndSuper(ClassDecl, Method, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/// Check for class method of the same name with incompatible types
|
/// Check for class method of the same name with incompatible types
|
||||||
|
@ -2299,10 +2301,11 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd,
|
||||||
}
|
}
|
||||||
ClsMap[Method->getSelector()] = Method;
|
ClsMap[Method->getSelector()] = Method;
|
||||||
/// The following allows us to typecheck messages to "Class".
|
/// The following allows us to typecheck messages to "Class".
|
||||||
AddFactoryMethodToGlobalPool(Method);
|
if (!AddFactoryMethodToGlobalPool(Method)) {
|
||||||
// verify that the class method conforms to the same definition of
|
// verify that the class method conforms to the same definition of
|
||||||
// parent methods if it shadows one.
|
// parent methods if it shadows one.
|
||||||
CompareMethodParamsInBaseAndSuper(ClassDecl, Method, false);
|
CompareMethodParamsInBaseAndSuper(ClassDecl, Method, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue