r179652 - Enhance the ObjC global method pool to record whether there were 0, 1, or >= 2 methods (with a particular selector) inside categories.

Argyrios Kyrtzidis akyrtzi at gmail.com
Tue Apr 16 17:08:58 PDT 2013


Author: akirtzidis
Date: Tue Apr 16 19:08:58 2013
New Revision: 179652

URL: http://llvm.org/viewvc/llvm-project?rev=179652&view=rev
Log:
Enhance the ObjC global method pool to record whether there were 0, 1, or >= 2 methods (with a particular selector) inside categories.

This is done by extending ObjCMethodList (which is only used by the global method pool) to have 2 extra bits of information.
We will later take advantage of this info in global method pool for the overridden methods calculation.

Modified:
    cfe/trunk/include/clang/Sema/ObjCMethodList.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaCodeComplete.cpp
    cfe/trunk/lib/Sema/SemaDeclObjC.cpp
    cfe/trunk/lib/Serialization/ASTReader.cpp
    cfe/trunk/lib/Serialization/ASTReaderInternals.h
    cfe/trunk/lib/Serialization/ASTWriter.cpp

Modified: cfe/trunk/include/clang/Sema/ObjCMethodList.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/ObjCMethodList.h?rev=179652&r1=179651&r2=179652&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/ObjCMethodList.h (original)
+++ cfe/trunk/include/clang/Sema/ObjCMethodList.h Tue Apr 16 19:08:58 2013
@@ -14,6 +14,8 @@
 #ifndef LLVM_CLANG_SEMA_OBJC_METHOD_LIST_H
 #define LLVM_CLANG_SEMA_OBJC_METHOD_LIST_H
 
+#include "llvm/ADT/PointerIntPair.h"
+
 namespace clang {
 
 class ObjCMethodDecl;
@@ -21,16 +23,17 @@ class ObjCMethodDecl;
 /// ObjCMethodList - a linked list of methods with different signatures.
 struct ObjCMethodList {
   ObjCMethodDecl *Method;
-  ObjCMethodList *Next;
+  /// \brief The next list object and 2 bits for extra info.
+  llvm::PointerIntPair<ObjCMethodList *, 2> NextAndExtraBits;
+
+  ObjCMethodList() : Method(0) { }
+  ObjCMethodList(ObjCMethodDecl *M, ObjCMethodList *C)
+    : Method(M), NextAndExtraBits(C, 0) { }
 
-  ObjCMethodList() {
-    Method = 0;
-    Next = 0;
-  }
-  ObjCMethodList(ObjCMethodDecl *M, ObjCMethodList *C) {
-    Method = M;
-    Next = C;
-  }
+  ObjCMethodList *getNext() const { return NextAndExtraBits.getPointer(); }
+  unsigned getBits() const { return NextAndExtraBits.getInt(); }
+  void setNext(ObjCMethodList *L) { NextAndExtraBits.setPointer(L); }
+  void setBits(unsigned B) { NextAndExtraBits.setInt(B); }
 };
 
 }

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=179652&r1=179651&r2=179652&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Tue Apr 16 19:08:58 2013
@@ -770,6 +770,8 @@ public:
   /// We need to maintain a list, since selectors can have differing signatures
   /// across classes. In Cocoa, this happens to be extremely uncommon (only 1%
   /// of selectors are "overloaded").
+  /// At the head of the list it is recorded whether there were 0, 1, or >= 2
+  /// methods inside categories with a particular selector.
   GlobalMethodPool MethodPool;
 
   /// Method selectors used in a \@selector expression. Used for implementation

Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=179652&r1=179651&r2=179652&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Tue Apr 16 19:08:58 2013
@@ -5471,7 +5471,7 @@ static void AddClassMessageCompletions(S
          M != MEnd; ++M) {
       for (ObjCMethodList *MethList = &M->second.second;
            MethList && MethList->Method; 
-           MethList = MethList->Next) {
+           MethList = MethList->getNext()) {
         if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents, 
                                     NumSelIdents))
           continue;
@@ -5644,7 +5644,7 @@ void Sema::CodeCompleteObjCInstanceMessa
          M != MEnd; ++M) {
       for (ObjCMethodList *MethList = &M->second.first;
            MethList && MethList->Method; 
-           MethList = MethList->Next) {
+           MethList = MethList->getNext()) {
         if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents, 
                                     NumSelIdents))
           continue;
@@ -7085,7 +7085,7 @@ void Sema::CodeCompleteObjCMethodDeclSel
     for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
                                                        &M->second.second;
          MethList && MethList->Method; 
-         MethList = MethList->Next) {
+         MethList = MethList->getNext()) {
       if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents, 
                                   NumSelIdents))
         continue;

Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=179652&r1=179651&r2=179652&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Tue Apr 16 19:08:58 2013
@@ -2085,17 +2085,23 @@ bool Sema::MatchTwoMethodDeclarations(co
 }
 
 void Sema::addMethodToGlobalList(ObjCMethodList *List, ObjCMethodDecl *Method) {
+  // Record at the head of the list whether there were 0, 1, or >= 2 methods
+  // inside categories.
+  if (isa<ObjCCategoryDecl>(Method->getDeclContext()))
+    if (List->getBits() < 2)
+      List->setBits(List->getBits()+1);
+
   // If the list is empty, make it a singleton list.
   if (List->Method == 0) {
     List->Method = Method;
-    List->Next = 0;
+    List->setNext(0);
     return;
   }
   
   // We've seen a method with this name, see if we have already seen this type
   // signature.
   ObjCMethodList *Previous = List;
-  for (; List; Previous = List, List = List->Next) {
+  for (; List; Previous = List, List = List->getNext()) {
     if (!MatchTwoMethodDeclarations(Method, List->Method))
       continue;
     
@@ -2124,7 +2130,7 @@ void Sema::addMethodToGlobalList(ObjCMet
   // We have a new signature for an existing method - add it.
   // This is extremely rare. Only 1% of Cocoa selectors are "overloaded".
   ObjCMethodList *Mem = BumpAlloc.Allocate<ObjCMethodList>();
-  Previous->Next = new (Mem) ObjCMethodList(Method, 0);
+  Previous->setNext(new (Mem) ObjCMethodList(Method, 0));
 }
 
 /// \brief Read the contents of the method pool for a given selector from
@@ -2186,7 +2192,7 @@ ObjCMethodDecl *Sema::LookupMethodInGlob
   // Gather the non-hidden methods.
   ObjCMethodList &MethList = instance ? Pos->second.first : Pos->second.second;
   llvm::SmallVector<ObjCMethodDecl *, 4> Methods;
-  for (ObjCMethodList *M = &MethList; M; M = M->Next) {
+  for (ObjCMethodList *M = &MethList; M; M = M->getNext()) {
     if (M->Method && !M->Method->isHidden()) {
       // If we're not supposed to warn about mismatches, we're done.
       if (!warn)

Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=179652&r1=179651&r2=179652&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Tue Apr 16 19:08:58 2013
@@ -428,8 +428,12 @@ ASTSelectorLookupTrait::ReadData(Selecto
   data_type Result;
 
   Result.ID = Reader.getGlobalSelectorID(F, ReadUnalignedLE32(d));
-  unsigned NumInstanceMethods = ReadUnalignedLE16(d);
-  unsigned NumFactoryMethods = ReadUnalignedLE16(d);
+  unsigned NumInstanceMethodsAndBits = ReadUnalignedLE16(d);
+  unsigned NumFactoryMethodsAndBits = ReadUnalignedLE16(d);
+  Result.InstanceBits = NumInstanceMethodsAndBits & 0x3;
+  Result.FactoryBits = NumFactoryMethodsAndBits & 0x3;
+  unsigned NumInstanceMethods = NumInstanceMethodsAndBits >> 2;
+  unsigned NumFactoryMethods = NumFactoryMethodsAndBits >> 2;
 
   // Load instance methods
   for (unsigned I = 0; I != NumInstanceMethods; ++I) {
@@ -2736,7 +2740,7 @@ static void moveMethodToBackOfGlobalList
   ObjCMethodList &Start = Method->isInstanceMethod()? Known->second.first
                                                     : Known->second.second;
   bool Found = false;
-  for (ObjCMethodList *List = &Start; List; List = List->Next) {
+  for (ObjCMethodList *List = &Start; List; List = List->getNext()) {
     if (!Found) {
       if (List->Method == Method) {
         Found = true;
@@ -2746,8 +2750,8 @@ static void moveMethodToBackOfGlobalList
       }
     }
 
-    if (List->Next)
-      List->Method = List->Next->Method;
+    if (List->getNext())
+      List->Method = List->getNext()->Method;
     else
       List->Method = Method;
   }
@@ -6114,13 +6118,16 @@ namespace clang { namespace serializatio
     ASTReader &Reader;
     Selector Sel;
     unsigned PriorGeneration;
+    unsigned InstanceBits;
+    unsigned FactoryBits;
     SmallVector<ObjCMethodDecl *, 4> InstanceMethods;
     SmallVector<ObjCMethodDecl *, 4> FactoryMethods;
 
   public:
     ReadMethodPoolVisitor(ASTReader &Reader, Selector Sel, 
                           unsigned PriorGeneration)
-      : Reader(Reader), Sel(Sel), PriorGeneration(PriorGeneration) { }
+      : Reader(Reader), Sel(Sel), PriorGeneration(PriorGeneration),
+        InstanceBits(0), FactoryBits(0) { }
     
     static bool visit(ModuleFile &M, void *UserData) {
       ReadMethodPoolVisitor *This
@@ -6153,6 +6160,8 @@ namespace clang { namespace serializatio
       
       This->InstanceMethods.append(Data.Instance.begin(), Data.Instance.end());
       This->FactoryMethods.append(Data.Factory.begin(), Data.Factory.end());
+      This->InstanceBits = Data.InstanceBits;
+      This->FactoryBits = Data.FactoryBits;
       return true;
     }
     
@@ -6165,6 +6174,9 @@ namespace clang { namespace serializatio
     ArrayRef<ObjCMethodDecl *> getFactoryMethods() const { 
       return FactoryMethods;
     }
+
+    unsigned getInstanceBits() const { return InstanceBits; }
+    unsigned getFactoryBits() const { return FactoryBits; }
   };
 } } // end namespace clang::serialization
 
@@ -6202,6 +6214,8 @@ void ASTReader::ReadMethodPool(Selector
   
   addMethodsToPool(S, Visitor.getInstanceMethods(), Pos->second.first);
   addMethodsToPool(S, Visitor.getFactoryMethods(), Pos->second.second);
+  Pos->second.first.setBits(Visitor.getInstanceBits());
+  Pos->second.second.setBits(Visitor.getFactoryBits());
 }
 
 void ASTReader::ReadKnownNamespaces(

Modified: cfe/trunk/lib/Serialization/ASTReaderInternals.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderInternals.h?rev=179652&r1=179651&r2=179652&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderInternals.h (original)
+++ cfe/trunk/lib/Serialization/ASTReaderInternals.h Tue Apr 16 19:08:58 2013
@@ -152,6 +152,8 @@ class ASTSelectorLookupTrait {
 public:
   struct data_type {
     SelectorID ID;
+    unsigned InstanceBits;
+    unsigned FactoryBits;
     SmallVector<ObjCMethodDecl *, 2> Instance;
     SmallVector<ObjCMethodDecl *, 2> Factory;
   };

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=179652&r1=179651&r2=179652&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Tue Apr 16 19:08:58 2013
@@ -2692,11 +2692,11 @@ public:
     clang::io::Emit16(Out, KeyLen);
     unsigned DataLen = 4 + 2 + 2; // 2 bytes for each of the method counts
     for (const ObjCMethodList *Method = &Methods.Instance; Method;
-         Method = Method->Next)
+         Method = Method->getNext())
       if (Method->Method)
         DataLen += 4;
     for (const ObjCMethodList *Method = &Methods.Factory; Method;
-         Method = Method->Next)
+         Method = Method->getNext())
       if (Method->Method)
         DataLen += 4;
     clang::io::Emit16(Out, DataLen);
@@ -2722,24 +2722,31 @@ public:
     clang::io::Emit32(Out, Methods.ID);
     unsigned NumInstanceMethods = 0;
     for (const ObjCMethodList *Method = &Methods.Instance; Method;
-         Method = Method->Next)
+         Method = Method->getNext())
       if (Method->Method)
         ++NumInstanceMethods;
 
     unsigned NumFactoryMethods = 0;
     for (const ObjCMethodList *Method = &Methods.Factory; Method;
-         Method = Method->Next)
+         Method = Method->getNext())
       if (Method->Method)
         ++NumFactoryMethods;
 
-    clang::io::Emit16(Out, NumInstanceMethods);
-    clang::io::Emit16(Out, NumFactoryMethods);
+    unsigned InstanceBits = Methods.Instance.getBits();
+    assert(InstanceBits < 4);
+    unsigned NumInstanceMethodsAndBits =
+        (NumInstanceMethods << 2) | InstanceBits;
+    unsigned FactoryBits = Methods.Factory.getBits();
+    assert(FactoryBits < 4);
+    unsigned NumFactoryMethodsAndBits = (NumFactoryMethods << 2) | FactoryBits;
+    clang::io::Emit16(Out, NumInstanceMethodsAndBits);
+    clang::io::Emit16(Out, NumFactoryMethodsAndBits);
     for (const ObjCMethodList *Method = &Methods.Instance; Method;
-         Method = Method->Next)
+         Method = Method->getNext())
       if (Method->Method)
         clang::io::Emit32(Out, Writer.getDeclID(Method->Method));
     for (const ObjCMethodList *Method = &Methods.Factory; Method;
-         Method = Method->Next)
+         Method = Method->getNext())
       if (Method->Method)
         clang::io::Emit32(Out, Writer.getDeclID(Method->Method));
 
@@ -2788,12 +2795,12 @@ void ASTWriter::WriteSelectors(Sema &Sem
         // Selector already exists. Did it change?
         bool changed = false;
         for (ObjCMethodList *M = &Data.Instance; !changed && M && M->Method;
-             M = M->Next) {
+             M = M->getNext()) {
           if (!M->Method->isFromASTFile())
             changed = true;
         }
         for (ObjCMethodList *M = &Data.Factory; !changed && M && M->Method;
-             M = M->Next) {
+             M = M->getNext()) {
           if (!M->Method->isFromASTFile())
             changed = true;
         }





More information about the cfe-commits mailing list