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
This commit is contained in:
parent
44d2973b6f
commit
e171601ff6
|
@ -66,7 +66,7 @@ protected:
|
|||
|
||||
virtual void InitializeSema(Sema &S);
|
||||
virtual void ForgetSema();
|
||||
virtual std::pair<ObjCMethodList,ObjCMethodList> ReadMethodPool(Selector Sel);
|
||||
virtual void ReadMethodPool(Selector Sel);
|
||||
virtual bool LookupUnqualified(LookupResult &R, Scope *S);
|
||||
};
|
||||
|
||||
|
|
|
@ -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<ObjCMethodList,ObjCMethodList> 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.
|
||||
|
|
|
@ -650,7 +650,7 @@ public:
|
|||
/// of -Wselector.
|
||||
llvm::DenseMap<Selector, SourceLocation> 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.
|
||||
|
|
|
@ -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<ObjCMethodList, ObjCMethodList>
|
||||
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.
|
||||
|
|
|
@ -231,9 +231,8 @@ void ChainedIncludesSource::InitializeSema(Sema &S) {
|
|||
void ChainedIncludesSource::ForgetSema() {
|
||||
return getFinalReader().ForgetSema();
|
||||
}
|
||||
std::pair<ObjCMethodList,ObjCMethodList>
|
||||
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);
|
||||
|
|
|
@ -879,10 +879,7 @@ LambdaScopeInfo *Sema::getCurLambda() {
|
|||
// Pin this vtable to this file.
|
||||
ExternalSemaSource::~ExternalSemaSource() {}
|
||||
|
||||
std::pair<ObjCMethodList, ObjCMethodList>
|
||||
ExternalSemaSource::ReadMethodPool(Selector Sel) {
|
||||
return std::pair<ObjCMethodList, ObjCMethodList>();
|
||||
}
|
||||
void ExternalSemaSource::ReadMethodPool(Selector Sel) { }
|
||||
|
||||
void ExternalSemaSource::ReadKnownNamespaces(
|
||||
SmallVectorImpl<NamespaceDecl *> &Namespaces) {
|
||||
|
|
|
@ -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>();
|
||||
ObjCMethodList *Mem = BumpAlloc.Allocate<ObjCMethodList>();
|
||||
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;
|
||||
|
|
|
@ -5216,30 +5216,6 @@ namespace clang { namespace serialization {
|
|||
llvm::SmallVector<ObjCMethodDecl *, 4> InstanceMethods;
|
||||
llvm::SmallVector<ObjCMethodDecl *, 4> FactoryMethods;
|
||||
|
||||
/// \brief Build an ObjCMethodList from a vector of Objective-C method
|
||||
/// declarations.
|
||||
ObjCMethodList
|
||||
buildObjCMethodList(const SmallVectorImpl<ObjCMethodDecl *> &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<ObjCMethodList>();
|
||||
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<ObjCMethodDecl *> getInstanceMethods() const {
|
||||
return InstanceMethods;
|
||||
}
|
||||
|
||||
/// \brief Retrieve the instance methods found by this visitor.
|
||||
ObjCMethodList getFactoryMethods() const {
|
||||
return buildObjCMethodList(FactoryMethods);
|
||||
ArrayRef<ObjCMethodDecl *> getFactoryMethods() const {
|
||||
return FactoryMethods;
|
||||
}
|
||||
};
|
||||
} } // end namespace clang::serialization
|
||||
|
||||
std::pair<ObjCMethodList, ObjCMethodList>
|
||||
ASTReader::ReadMethodPool(Selector Sel) {
|
||||
/// \brief Add the given set of methods to the method list.
|
||||
static void addMethodsToPool(Sema &S, ArrayRef<ObjCMethodDecl *> 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<ObjCMethodList, ObjCMethodList> 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(
|
||||
|
|
Loading…
Reference in New Issue