Yesterday I discovered that 78% of all selectors in "Cocoa.h" take 0/1 argument.

This motivated implementing a devious clattner inspired solution:-)

This approach uses a small value "Selector" class to point to an IdentifierInfo for the 0/1 case. For multi-keyword selectors, we instantiate a MultiKeywordSelector object (previously known as SelectorInfo). Now, the incremental cost for selectors is only 24,800 for Cocoa.h! This saves 156,592 bytes, or 86%!! The size reduction is also the result of getting rid of the AST slot, which was not strictly necessary (we will associate a selector with it's method using another table...most likely in Sema).

This change was critical to make now, before we have too many clients.

I still need to add some comments to the Selector class...will likely add later today/tomorrow.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@42452 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Parse/ParseObjc.cpp b/Parse/ParseObjc.cpp
index ba29ede..3317b88 100644
--- a/Parse/ParseObjc.cpp
+++ b/Parse/ParseObjc.cpp
@@ -502,50 +502,35 @@
   return Ty;
 }
 
-static SelectorInfo *ObjcGetUnarySelectorInfo(
-  IdentifierInfo *unarySel,
-  llvm::FoldingSet<SelectorInfo> &SelTab) 
+Selector Parser::ObjcGetUnarySelector(IdentifierInfo *unarySel)
 {
-  // Unique selector, to guarantee there is one per name.
-  llvm::SmallVector<IdentifierInfo *, 1> IIV;
-  llvm::FoldingSetNodeID ID;
-  
-  IIV.push_back(unarySel);
-  SelectorInfo::Profile(ID, &IIV[0], 0);
-
-  void *InsertPos = 0;
-  if (SelectorInfo *SI = SelTab.FindNodeOrInsertPos(ID, InsertPos))
-    return SI;
-
-  // SelectorInfo objects are not allocated with new because they have a
-  // variable size array (for parameter types) at the end of them.
-  SelectorInfo *SI = 
-    (SelectorInfo*)malloc(sizeof(SelectorInfo) + sizeof(IdentifierInfo *));
-  new (SI) SelectorInfo(IIV[0]);
-  SelTab.InsertNode(SI, InsertPos);
-  return SI;
+  return Selector(unarySel, 0);
 }
 
-static SelectorInfo *ObjcGetKeywordSelectorInfo(
-  llvm::SmallVectorImpl<IdentifierInfo *> &IIV,
-  llvm::FoldingSet<SelectorInfo> &SelTab) 
-{  
+Selector Parser::ObjcGetKeywordSelector(
+  llvm::SmallVectorImpl<IdentifierInfo *> &IIV) 
+{
+  if (IIV.size() == 1)
+    return Selector(IIV[0], 1);
+
+  llvm::FoldingSet<MultiKeywordSelector> &SelTab = PP.getSelectorTable();
+  
   // Unique selector, to guarantee there is one per name.
   llvm::FoldingSetNodeID ID;
-  SelectorInfo::Profile(ID, &IIV[0], IIV.size());
+  MultiKeywordSelector::Profile(ID, &IIV[0], IIV.size());
 
   void *InsertPos = 0;
-  if (SelectorInfo *SI = SelTab.FindNodeOrInsertPos(ID, InsertPos))
-    return SI;
-
-  // SelectorInfo objects are not allocated with new because they have a
+  if (MultiKeywordSelector *SI = SelTab.FindNodeOrInsertPos(ID, InsertPos)) {
+    return Selector(SI);
+  }
+  // MultiKeywordSelector objects are not allocated with new because they have a
   // variable size array (for parameter types) at the end of them.
-  SelectorInfo *SI = 
-    (SelectorInfo*)malloc(sizeof(SelectorInfo) + 
-                          IIV.size()*sizeof(IdentifierInfo *));
-  new (SI) SelectorInfo(IIV.size(), &IIV[0]);
+  MultiKeywordSelector *SI = 
+    (MultiKeywordSelector*)malloc(sizeof(MultiKeywordSelector) + 
+                                  IIV.size()*sizeof(IdentifierInfo *));
+  new (SI) MultiKeywordSelector(IIV.size(), &IIV[0]);
   SelTab.InsertNode(SI, InsertPos);
-  return SI;
+  return Selector(SI);
 }
 
 ///   objc-method-decl:
@@ -646,9 +631,8 @@
     if (getLang().ObjC2 && Tok.getKind() == tok::kw___attribute) 
       methodAttrs = ParseAttributes();
       
-    SelectorInfo *SI = ObjcGetKeywordSelectorInfo(KeyIdents, 
-                                                  PP.getSelectorTable());
-    return Actions.ObjcBuildMethodDeclaration(mLoc, mType, ReturnType, SI, 
+    Selector Sel = ObjcGetKeywordSelector(KeyIdents);
+    return Actions.ObjcBuildMethodDeclaration(mLoc, mType, ReturnType, Sel, 
                                               &KeyTypes[0], &ArgNames[0],
 					      methodAttrs, MethodImplKind);
   } else if (!selIdent) {
@@ -658,8 +642,8 @@
   if (getLang().ObjC2 && Tok.getKind() == tok::kw___attribute) 
     methodAttrs = ParseAttributes();
 
-  SelectorInfo *SI = ObjcGetUnarySelectorInfo(selIdent, PP.getSelectorTable());
-  return Actions.ObjcBuildMethodDeclaration(mLoc, mType, ReturnType, SI, 
+  Selector Sel = ObjcGetUnarySelector(selIdent);
+  return Actions.ObjcBuildMethodDeclaration(mLoc, mType, ReturnType, Sel, 
                                             0, 0, methodAttrs, MethodImplKind);
 }
 
@@ -1255,21 +1239,20 @@
   SourceLocation RBracloc = ConsumeBracket(); // consume ']'
   
   if (KeyIdents.size()) {
-    SelectorInfo *SI = ObjcGetKeywordSelectorInfo(KeyIdents, 
-                                                  PP.getSelectorTable());
+    Selector sel = ObjcGetKeywordSelector(KeyIdents);
     // We've just parsed a keyword message.
     if (ReceiverName) 
-      return Actions.ActOnClassMessage(ReceiverName, SI, LBracloc, RBracloc,
+      return Actions.ActOnClassMessage(ReceiverName, sel, LBracloc, RBracloc,
                                        &KeyExprs[0]);
-    return Actions.ActOnInstanceMessage(ReceiverExpr, SI, LBracloc, RBracloc,
+    return Actions.ActOnInstanceMessage(ReceiverExpr, sel, LBracloc, RBracloc,
                                         &KeyExprs[0]);
   }
-  SelectorInfo *SI = ObjcGetUnarySelectorInfo(selIdent, PP.getSelectorTable());
+  Selector sel = ObjcGetUnarySelector(selIdent);
 
   // We've just parsed a unary message (a message with no arguments).
   if (ReceiverName) 
-    return Actions.ActOnClassMessage(ReceiverName, SI, LBracloc, RBracloc, 0);
-  return Actions.ActOnInstanceMessage(ReceiverExpr, SI, LBracloc, RBracloc, 0);
+    return Actions.ActOnClassMessage(ReceiverName, sel, LBracloc, RBracloc, 0);
+  return Actions.ActOnInstanceMessage(ReceiverExpr, sel, LBracloc, RBracloc, 0);
 }
 
 Parser::ExprResult Parser::ParseObjCStringLiteral() {