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.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@148889 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index 02ba415..432e3dd 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -1931,9 +1931,7 @@
   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 @@
   // 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 @@
   
   // 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 @@
   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 @@
                                                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 @@
     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;