[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