From 2e3d8c0815acaf1bc5995ebe56cea07471e5c9c7 Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Wed, 17 Apr 2013 00:08:58 +0000 Subject: [PATCH] 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@179652 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Sema/ObjCMethodList.h | 23 ++++++++++++---------- include/clang/Sema/Sema.h | 2 ++ lib/Sema/SemaCodeComplete.cpp | 6 +++--- lib/Sema/SemaDeclObjC.cpp | 14 +++++++++---- lib/Serialization/ASTReader.cpp | 26 +++++++++++++++++++------ lib/Serialization/ASTReaderInternals.h | 2 ++ lib/Serialization/ASTWriter.cpp | 27 ++++++++++++++++---------- 7 files changed, 67 insertions(+), 33 deletions(-) diff --git a/include/clang/Sema/ObjCMethodList.h b/include/clang/Sema/ObjCMethodList.h index 225c13776c..94e380721d 100644 --- a/include/clang/Sema/ObjCMethodList.h +++ b/include/clang/Sema/ObjCMethodList.h @@ -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; - - ObjCMethodList() { - Method = 0; - Next = 0; - } - ObjCMethodList(ObjCMethodDecl *M, ObjCMethodList *C) { - Method = M; - Next = C; - } + /// \brief The next list object and 2 bits for extra info. + llvm::PointerIntPair NextAndExtraBits; + + ObjCMethodList() : Method(0) { } + ObjCMethodList(ObjCMethodDecl *M, ObjCMethodList *C) + : Method(M), NextAndExtraBits(C, 0) { } + + 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); } }; } diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index f95d6a4321..b188ef36ae 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -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 diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index a72e74b5aa..fd2ce1749f 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -5471,7 +5471,7 @@ static void AddClassMessageCompletions(Sema &SemaRef, Scope *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::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver, 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::CodeCompleteObjCMethodDeclSelector(Scope *S, 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; diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 48f0decc2c..a6f8bf7f57 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -2085,17 +2085,23 @@ bool Sema::MatchTwoMethodDeclarations(const ObjCMethodDecl *left, } 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(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(ObjCMethodList *List, ObjCMethodDecl *Method) { // 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(); - 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::LookupMethodInGlobalPool(Selector Sel, SourceRange R, // Gather the non-hidden methods. ObjCMethodList &MethList = instance ? Pos->second.first : Pos->second.second; llvm::SmallVector 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) diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 4302f8bb53..9893823a12 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -428,8 +428,12 @@ ASTSelectorLookupTrait::ReadData(Selector, const unsigned char* d, 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(Sema &S, ObjCMethodDecl *Method) { 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(Sema &S, ObjCMethodDecl *Method) { } } - 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 serialization { ASTReader &Reader; Selector Sel; unsigned PriorGeneration; + unsigned InstanceBits; + unsigned FactoryBits; SmallVector InstanceMethods; SmallVector 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 serialization { 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 serialization { ArrayRef 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 Sel) { 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( diff --git a/lib/Serialization/ASTReaderInternals.h b/lib/Serialization/ASTReaderInternals.h index 327da4403a..9149b18480 100644 --- a/lib/Serialization/ASTReaderInternals.h +++ b/lib/Serialization/ASTReaderInternals.h @@ -152,6 +152,8 @@ class ASTSelectorLookupTrait { public: struct data_type { SelectorID ID; + unsigned InstanceBits; + unsigned FactoryBits; SmallVector Instance; SmallVector Factory; }; diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index e98708d8f5..b6d25d22d5 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -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 &SemaRef) { // 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; } -- 2.40.0