[cfe-commits] r42452 - in /cfe/trunk: AST/Expr.cpp Lex/IdentifierTable.cpp Parse/ParseObjc.cpp Sema/Sema.h Sema/SemaDecl.cpp Sema/SemaExpr.cpp clang.xcodeproj/project.pbxproj include/clang/AST/ASTContext.h include/clang/AST/Decl.h include/clang/AST/Expr.h include/clang/Lex/IdentifierTable.h include/clang/Lex/Preprocessor.h include/clang/Parse/Action.h include/clang/Parse/Parser.h

Chris Lattner clattner at apple.com
Wed Oct 3 22:42:01 PDT 2007


On Sep 28, 2007, at 3:22 PM, Steve Naroff wrote:
> Author: snaroff
> Date: Fri Sep 28 17:22:11 2007
> New Revision: 42452
>
> URL: http://llvm.org/viewvc/llvm-project?rev=42452&view=rev
> Log:
>
> 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).

Very nice Steve!  Some comments:

> ====================================================================== 
> ========
> --- cfe/trunk/include/clang/Lex/IdentifierTable.h (original)
> +++ cfe/trunk/include/clang/Lex/IdentifierTable.h Fri Sep 28  
> 17:22:11 2007
> @@ -170,28 +170,24 @@
>    void AddKeywords(const LangOptions &LangOpts);
>  };
>
> +/// MultiKeywordSelector - One of these variable length records is  
> kept for each
> +/// parsed selector (similar in spirit to IdentifierInfo). We use  
> a folding set
> +/// to unique aggregate names (keyword selectors in ObjC parlance).
> +class MultiKeywordSelector : public llvm::FoldingSetNode {

I don't think there is any reason to export the definition of  
MultiKeywordSelector in the header file.  Can you make it just  
forward-declared here and suck the definition/implementation into  
IdentifierTable.cpp?  Clients should never interact with  
MultiKeywordSelector, they should only interact with Selector.

Ahh, I see you added this later:
/// The only reason it appears in this header is FoldingSet needs to  
see it:-(

Presumably this is because Preprocessor contains:
   /// Selectors - This table contains all the selectors in the  
program. Unlike
   /// IdentifierTable above, this table *isn't* populated by the  
preprocessor.
   /// It is declared/instantiated here because it's role/lifetime is
   /// conceptually similar the IdentifierTable. In addition, the  
current control
   /// flow (in clang::ParseAST()), make it convenient to put here.
   /// FIXME: Make sure the lifetime of Identifiers/Selectors *isn't*  
tied to
   /// the lifetime fo the preprocessor.
   llvm::FoldingSet<MultiKeywordSelector> Selectors;

This declaration is unfortunate for two reasons:
1. it requires MultiKeywordSelector to be exported out of  
IdentifierTable.cpp, and
2. it requires preprocessor and IdentifierTable.h to #include  
FoldingSet.h

Instead of doing this, I'd suggest adding the following to  
IdentifierTable.h:

class SelectorUniquingTable {
   void *Impl;  // Actually a FoldingSet<MultiKeywordSelector>*
   SelectorUniquingTable(const SelectorUniquingTable&); // DISABLED:  
DO NOT IMPLEMENT
   void operator=(const SelectorUniquingTable&); // DISABLED: DO NOT  
IMPLEMENT
public:
   SelectorUniquingTable();  // new's the foldingset
   ~SelectorUniquingTable();  // delete's the foldingset

   Selector getSelector(unsigned nKeys, IdentifierInfo **IIV);
   Selector getUnarySelector(IdentifierInfo *ID);
   Selector getNullarySelector(IdentifierInfo *ID);
};

With this definition, Parser can contain an instance of  
SelectorUniquingTable instead of a folding set, getting rid of the  
#include of FoldingSet.h and allowing MultiKeywordSelector to become  
private to the .cpp file.

Another benefit is that stuff like this (from Selector and  
MultiKeywordSelector):
> +  friend class Parser; // only the Parser can create these.

can now befriend the SelectorUniquingTable class instead, fixing a  
layering problem (because ideally IdentifierTable will sink into  
libbasic).


> +  IdentifierInfo *getIdentifierInfoForSlot(unsigned i) {
> +    assert((i < NumArgs) && "getIdentifierInfoForSlot(): illegal  
> index");
> +    return keyword_begin()[i];
> +  }

This method should be const.

+  friend class llvm::FoldingSet<MultiKeywordSelector>;

This can go away when it is in the .cpp file, because all the access  
can be public.

> +class Selector {

The selector class needs a comment above it.

> +  // Derive the full selector name, placing the result into  
> methodBuffer.
> +  // As a convenience, a pointer to the first character is returned.
> +  // Example usage: llvm::SmallString<128> mbuf; Selector->getName 
> (mbuf);
> +  char *getName(llvm::SmallVectorImpl<char> &methodBuffer);

Why is this implemented in ParseObjc.cpp?  It seems like it should be  
in IdentifierTable.cpp.

>
> Modified: cfe/trunk/Sema/SemaDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/ 
> SemaDecl.cpp?rev=42452&r1=42451&r2=42452&view=diff
>
> ====================================================================== 
> ========
> --- cfe/trunk/Sema/SemaDecl.cpp (original)
> +++ cfe/trunk/Sema/SemaDecl.cpp Fri Sep 28 17:22:11 2007
>
> @@ -1206,35 +1206,35 @@
>  static void ImplMethodsVsClassMethods(Sema* objSema,
>  				      ObjcImplementationDecl* IMPDecl,
>                                        ObjcInterfaceDecl* IDecl) {
> -  llvm::DenseMap<const SelectorInfo*, char> InsMap;
> +  llvm::DenseMap<void *, char> InsMap;

Since this code was written, a new llvm::DenseSet was added.  You  
should be able to switch this to use DenseSet, which makes it more  
obvious what you're doing here.

Also, instead of using .getAsOpaquePtr(), I think it would make sense  
to teach the hash table how to handle Selectors.  It seems useful to  
other people and can be added easily to IdentifierInfo.h.

> ====================================================================== 
> ========
> --- cfe/trunk/include/clang/AST/Expr.h (original)
> +++ cfe/trunk/include/clang/AST/Expr.h Fri Sep 28 17:22:11 2007
> @@ -1100,12 +1101,17 @@
>    Expr *getReceiver() { return SubExprs[RECEIVER]; }
>
>    /// getNumArgs - Return the number of actual arguments to this  
> call.
> +  unsigned getNumArgs() const { return SelName.getNumArgs(); }
> +
> +/// getArg - Return the specified argument.
> +  Expr *getArg(unsigned Arg) {
> +    assert(Arg < SelName.getNumArgs() && "Arg access out of range!");
> +    return SubExprs[Arg+ARGS_START];
> +  }

Funky comment indentation.

Overall, huge leap forward!

-Chris




More information about the cfe-commits mailing list