[cfe-commits] r62599 - in /cfe/trunk: include/clang/Parse/DeclSpec.h lib/Parse/DeclSpec.cpp lib/Parse/ParseDecl.cpp lib/Parse/ParseExpr.cpp lib/Sema/SemaDecl.cpp

Chris Lattner sabre at nondot.org
Tue Jan 20 11:11:22 PST 2009


Author: lattner
Date: Tue Jan 20 13:11:22 2009
New Revision: 62599

URL: http://llvm.org/viewvc/llvm-project?rev=62599&view=rev
Log:
Optimize Declarator to avoid malloc/free traffic for the argument list of a
function DeclaratorChunk in common cases.  This uses a fixed array in 
Declarator when it is small enough for the first function declarator chunk
in a declarator.

This eliminates all malloc/free traffic from DeclaratorChunk::getFunction
when running on Cocoa.h except for five functions: signal/bsd_signal/sigset,
which have multiple Function DeclChunk's, and 
CFUUIDCreateWithBytes/CFUUIDGetConstantUUIDWithBytes, which take more than
16 arguments.

This patch was pair programmed with Steve.


Modified:
    cfe/trunk/include/clang/Parse/DeclSpec.h
    cfe/trunk/lib/Parse/DeclSpec.cpp
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Parse/ParseExpr.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp

Modified: cfe/trunk/include/clang/Parse/DeclSpec.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/DeclSpec.h?rev=62599&r1=62598&r2=62599&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Parse/DeclSpec.h Tue Jan 20 13:11:22 2009
@@ -18,6 +18,7 @@
 #include "clang/Parse/AttributeList.h"
 #include "clang/Lex/Token.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/PointerIntPair.h"
 
 namespace clang {
   struct LangOptions;
@@ -241,7 +242,6 @@
            getTypeSpecSign() != DeclSpec::TSS_unspecified;
   }
   
-  
   /// getParsedSpecifiers - Return a bitmask of which flavors of specifiers this
   /// DeclSpec includes.
   ///
@@ -486,7 +486,7 @@
     /// declaration of a member function), it will be stored here as a
     /// sequence of tokens to be parsed once the class definition is
     /// complete. Non-NULL indicates that there is a default argument.
-    CachedTokens   *DefaultArgTokens;
+    CachedTokens *DefaultArgTokens;
 
     ParamInfo() {}
     ParamInfo(IdentifierInfo *ident, SourceLocation iloc, Action::DeclTy *param,
@@ -509,6 +509,9 @@
     /// The qualifier bitmask values are the same as in QualType. 
     unsigned TypeQuals : 3;
 
+    /// DeleteArgInfo - If this is true, we need to delete[] ArgInfo.
+    bool DeleteArgInfo : 1;
+
     /// NumArgs - This is the number of formal arguments provided for the
     /// declarator.
     unsigned NumArgs;
@@ -519,7 +522,8 @@
     ParamInfo *ArgInfo;
     
     void destroy() {
-      delete[] ArgInfo;
+      if (DeleteArgInfo)
+        delete[] ArgInfo;
     }
   };
 
@@ -538,6 +542,16 @@
     BlockPointerTypeInfo Cls;
   };
   
+  void destroy() {
+    switch (Kind) {
+    default: assert(0 && "Unknown decl type!");
+    case DeclaratorChunk::Function:     return Fun.destroy();
+    case DeclaratorChunk::Pointer:      return Ptr.destroy();
+    case DeclaratorChunk::BlockPointer: return Cls.destroy();
+    case DeclaratorChunk::Reference:    return Ref.destroy();
+    case DeclaratorChunk::Array:        return Arr.destroy();
+    }
+  }
   
   /// getAttrs - If there are attributes applied to this declaratorchunk, return
   /// them.
@@ -592,26 +606,13 @@
     return I;
   }
   
-  /// getFunction - Return a DeclaratorChunk for a function.
+  /// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function.
+  /// "TheDeclarator" is the declarator that this will be added to.
   static DeclaratorChunk getFunction(bool hasProto, bool isVariadic,
                                      ParamInfo *ArgInfo, unsigned NumArgs,
-                                     unsigned TypeQuals, SourceLocation Loc) {
-    DeclaratorChunk I;
-    I.Kind             = Function;
-    I.Loc              = Loc;
-    I.Fun.hasPrototype = hasProto;
-    I.Fun.isVariadic   = isVariadic;
-    I.Fun.TypeQuals    = TypeQuals;
-    I.Fun.NumArgs      = NumArgs;
-    I.Fun.ArgInfo      = 0;
-    
-    // new[] an argument array if needed.
-    if (NumArgs) {
-      I.Fun.ArgInfo = new DeclaratorChunk::ParamInfo[NumArgs];
-      memcpy(I.Fun.ArgInfo, ArgInfo, sizeof(ArgInfo[0])*NumArgs);
-    }
-    return I;
-  }
+                                     unsigned TypeQuals, SourceLocation Loc,
+                                     Declarator &TheDeclarator);
+  
   /// getBlockPointer - Return a DeclaratorChunk for a block.
   ///
   static DeclaratorChunk getBlockPointer(unsigned TypeQuals, 
@@ -635,13 +636,8 @@
 /// Instances of this class should be a transient object that lives on the
 /// stack, not objects that are allocated in large quantities on the heap.
 class Declarator {
-  const DeclSpec &DS;
-  CXXScopeSpec SS;
-  IdentifierInfo *Identifier;
-  SourceLocation IdentifierLoc;
-  
 public:
-  enum TheContext {
+   enum TheContext {
     FileContext,         // File scope declaration.
     PrototypeContext,    // Within a function prototype.
     KNRTypeListContext,  // K&R type definition list for formals.
@@ -666,6 +662,11 @@
   };
 
 private:
+  const DeclSpec &DS;
+  CXXScopeSpec SS;
+  IdentifierInfo *Identifier;
+  SourceLocation IdentifierLoc;
+  
   /// Context - Where we are parsing this declarator.
   ///
   TheContext Context;
@@ -702,10 +703,18 @@
     OverloadedOperatorKind OperatorKind;
   };
 
+  /// InlineParams - This is a local array used for the first function decl
+  /// chunk to avoid going to the heap for the common case when we have one
+  /// function chunk in the declarator.
+  friend class DeclaratorChunk;
+  DeclaratorChunk::ParamInfo InlineParams[16];
+  bool InlineParamsUsed;
+  
 public:
   Declarator(const DeclSpec &ds, TheContext C)
     : DS(ds), Identifier(0), Context(C), Kind(DK_Abstract), InvalidType(false),
-      GroupingParens(false), AttrList(0), AsmLabel(0), Type(0) {
+      GroupingParens(false), AttrList(0), AsmLabel(0), Type(0),
+      InlineParamsUsed(false) {
   }
   
   ~Declarator() {
@@ -741,25 +750,14 @@
     IdentifierLoc = SourceLocation();
     Kind = DK_Abstract;
 
-    for (unsigned i = 0, e = DeclTypeInfo.size(); i != e; ++i) {
-      if (DeclTypeInfo[i].Kind == DeclaratorChunk::Function)
-        DeclTypeInfo[i].Fun.destroy();
-      else if (DeclTypeInfo[i].Kind == DeclaratorChunk::Pointer)
-        DeclTypeInfo[i].Ptr.destroy();
-      else if (DeclTypeInfo[i].Kind == DeclaratorChunk::BlockPointer)
-        DeclTypeInfo[i].Cls.destroy();
-      else if (DeclTypeInfo[i].Kind == DeclaratorChunk::Reference)
-        DeclTypeInfo[i].Ref.destroy();
-      else if (DeclTypeInfo[i].Kind == DeclaratorChunk::Array)
-        DeclTypeInfo[i].Arr.destroy();
-      else
-        assert(0 && "Unknown decl type!");
-    }
+    for (unsigned i = 0, e = DeclTypeInfo.size(); i != e; ++i)
+      DeclTypeInfo[i].destroy();
     DeclTypeInfo.clear();
     delete AttrList;
     AttrList = 0;
     AsmLabel = 0;
     Type = 0;
+    InlineParamsUsed = false;
   }
   
   /// mayOmitIdentifier - Return true if the identifier is either optional or
@@ -783,7 +781,7 @@
     return !hasGroupingParens() &&
            (Context == FileContext  ||
             Context == BlockContext ||
-            Context == ForContext     );
+            Context == ForContext);
   }
   
   /// isPastIdentifier - Return true if we have parsed beyond the point where
@@ -908,7 +906,6 @@
   }
 };
 
-
 } // end namespace clang
 
 #endif

Modified: cfe/trunk/lib/Parse/DeclSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/DeclSpec.cpp?rev=62599&r1=62598&r2=62599&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/DeclSpec.cpp (original)
+++ cfe/trunk/lib/Parse/DeclSpec.cpp Tue Jan 20 13:11:22 2009
@@ -14,6 +14,7 @@
 #include "clang/Parse/DeclSpec.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/LangOptions.h"
+#include "llvm/ADT/STLExtras.h"
 using namespace clang;
 
 
@@ -23,6 +24,43 @@
 }
 
 
+/// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function.
+/// "TheDeclarator" is the declarator that this will be added to.
+DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic,
+                                             ParamInfo *ArgInfo,
+                                             unsigned NumArgs,
+                                             unsigned TypeQuals,
+                                             SourceLocation Loc,
+                                             Declarator &TheDeclarator) {
+  DeclaratorChunk I;
+  I.Kind             = Function;
+  I.Loc              = Loc;
+  I.Fun.hasPrototype = hasProto;
+  I.Fun.isVariadic   = isVariadic;
+  I.Fun.DeleteArgInfo = false;
+  I.Fun.TypeQuals    = TypeQuals;
+  I.Fun.NumArgs      = NumArgs;
+  I.Fun.ArgInfo      = 0;
+  
+  // new[] an argument array if needed.
+  if (NumArgs) {
+    // If the 'InlineParams' in Declarator is unused and big enough, put our
+    // parameter list there (in an effort to avoid new/delete traffic).  If it
+    // is already used (consider a function returning a function pointer) or too
+    // small (function taking too many arguments), go to the heap.
+    if (!TheDeclarator.InlineParamsUsed && 
+        NumArgs <= llvm::array_lengthof(TheDeclarator.InlineParams)) {
+      I.Fun.ArgInfo = TheDeclarator.InlineParams;
+      I.Fun.DeleteArgInfo = false;
+      TheDeclarator.InlineParamsUsed = true;
+    } else {
+      I.Fun.ArgInfo = new DeclaratorChunk::ParamInfo[NumArgs];
+      I.Fun.DeleteArgInfo = true;
+    }
+    memcpy(I.Fun.ArgInfo, ArgInfo, sizeof(ArgInfo[0])*NumArgs);
+  }
+  return I;
+}
 
 /// getParsedSpecifiers - Return a bitmask of which flavors of specifiers this
 ///

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=62599&r1=62598&r2=62599&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Tue Jan 20 13:11:22 2009
@@ -1854,7 +1854,7 @@
                                                /*variadic*/ false,
                                                /*arglist*/ 0, 0,
                                                DS.getTypeQualifiers(),
-                                               LParenLoc));
+                                               LParenLoc, D));
     return;
   } 
   
@@ -2013,7 +2013,7 @@
   D.AddTypeInfo(DeclaratorChunk::getFunction(/*proto*/true, IsVariadic,
                                              &ParamInfo[0], ParamInfo.size(),
                                              DS.getTypeQualifiers(),
-                                             LParenLoc));
+                                             LParenLoc, D));
 }
 
 /// ParseFunctionDeclaratorIdentifierList - While parsing a function declarator
@@ -2080,7 +2080,7 @@
   // has no prototype.
   D.AddTypeInfo(DeclaratorChunk::getFunction(/*proto*/false, /*varargs*/false,
                                              &ParamInfo[0], ParamInfo.size(),
-                                             /*TypeQuals*/0, LParenLoc));
+                                             /*TypeQuals*/0, LParenLoc, D));
   
   // If we have the closing ')', eat it and we're done.
   MatchRHSPunctuation(tok::r_paren, LParenLoc);

Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=62599&r1=62598&r2=62599&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Tue Jan 20 13:11:22 2009
@@ -1222,7 +1222,8 @@
   } else {
     // Otherwise, pretend we saw (void).
     ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(true, false,
-                                                       0, 0, 0, CaretLoc));
+                                                       0, 0, 0, CaretLoc,
+                                                       ParamInfo));
   }
 
   // Inform sema that we are starting a block.

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=62599&r1=62598&r2=62599&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Jan 20 13:11:22 2009
@@ -2772,7 +2772,7 @@
   Error = Error; // Silence warning.
   assert(!Error && "Error setting up implicit decl!");
   Declarator D(DS, Declarator::BlockContext);
-  D.AddTypeInfo(DeclaratorChunk::getFunction(false, false, 0, 0, 0, Loc));
+  D.AddTypeInfo(DeclaratorChunk::getFunction(false, false, 0, 0, 0, Loc, D));
   D.SetIdentifier(&II, Loc);
   
   // Insert this function into translation-unit scope.





More information about the cfe-commits mailing list