Cache macro expander objects to avoid thrashing malloc in heavy expansion situations.

This doesn't significantly improve carbon.h, but it does speed up
INPUTS/macro_pounder_obj.c by 48%

llvm-svn: 39864
This commit is contained in:
Chris Lattner 2007-07-15 00:25:26 +00:00
parent 03928c7f9a
commit c02c4abe5b
4 changed files with 86 additions and 23 deletions

View File

@ -233,13 +233,17 @@ const LexerToken &MacroArgs::getStringifiedArgument(unsigned ArgNo,
/// Create a macro expander for the specified macro with the specified actual
/// arguments. Note that this ctor takes ownership of the ActualArgs pointer.
MacroExpander::MacroExpander(LexerToken &Tok, MacroArgs *Actuals,
Preprocessor &pp)
: Macro(Tok.getIdentifierInfo()->getMacroInfo()),
ActualArgs(Actuals), PP(pp), CurToken(0),
InstantiateLoc(Tok.getLocation()),
AtStartOfLine(Tok.isAtStartOfLine()),
HasLeadingSpace(Tok.hasLeadingSpace()) {
void MacroExpander::Init(LexerToken &Tok, MacroArgs *Actuals) {
// If the client is reusing a macro expander, make sure to free any memory
// associated with it.
destroy();
Macro = Tok.getIdentifierInfo()->getMacroInfo();
ActualArgs = Actuals;
CurToken = 0;
InstantiateLoc = Tok.getLocation();
AtStartOfLine = Tok.isAtStartOfLine();
HasLeadingSpace = Tok.hasLeadingSpace();
MacroTokens = &*Macro->tokens_begin();
NumMacroTokens = Macro->tokens_end()-Macro->tokens_begin();
@ -254,14 +258,23 @@ MacroExpander::MacroExpander(LexerToken &Tok, MacroArgs *Actuals,
Macro->DisableMacro();
}
/// Create a macro expander for the specified token stream. This does not
/// take ownership of the specified token vector.
MacroExpander::MacroExpander(const LexerToken *TokArray, unsigned NumToks,
Preprocessor &pp)
: Macro(0), ActualArgs(0), PP(pp), MacroTokens(TokArray),
NumMacroTokens(NumToks), CurToken(0),
InstantiateLoc(SourceLocation()), AtStartOfLine(false),
HasLeadingSpace(false) {
void MacroExpander::Init(const LexerToken *TokArray, unsigned NumToks) {
// If the client is reusing a macro expander, make sure to free any memory
// associated with it.
destroy();
Macro = 0;
ActualArgs = 0;
MacroTokens = TokArray;
NumMacroTokens = NumToks;
CurToken = 0;
InstantiateLoc = SourceLocation();
AtStartOfLine = false;
HasLeadingSpace = false;
// Set HasLeadingSpace/AtStartOfLine so that the first token will be
// returned unmodified.
@ -272,7 +285,7 @@ MacroExpander::MacroExpander(const LexerToken *TokArray, unsigned NumToks,
}
MacroExpander::~MacroExpander() {
void MacroExpander::destroy() {
// If this was a function-like macro that actually uses its arguments, delete
// the expanded tokens.
if (Macro && MacroTokens != &*Macro->tokens_begin())

View File

@ -48,7 +48,7 @@ Preprocessor::Preprocessor(Diagnostic &diags, const LangOptions &opts,
SourceMgr(SM), HeaderInfo(Headers), Identifiers(opts),
CurLexer(0), CurDirLookup(0), CurMacroExpander(0), Callbacks(0) {
ScratchBuf = new ScratchBuffer(SourceMgr);
// Clear stats.
NumDirectives = NumDefined = NumUndefined = NumPragma = 0;
NumIf = NumElse = NumEndif = 0;
@ -65,6 +65,7 @@ Preprocessor::Preprocessor(Diagnostic &diags, const LangOptions &opts,
// Macro expansion is enabled.
DisableMacroExpansion = false;
InMacroArgs = false;
NumCachedMacroExpanders = 0;
// "Poison" __VA_ARGS__, which can only appear in the expansion of a macro.
// This gets unpoisoned where it is allowed.
@ -88,6 +89,10 @@ Preprocessor::~Preprocessor() {
IncludeMacroStack.pop_back();
}
// Free any cached macro expanders.
for (unsigned i = 0, e = NumCachedMacroExpanders; i != e; ++i)
delete MacroExpanderCache[i];
// Release pragma information.
delete PragmaHandlers;
@ -386,7 +391,12 @@ void Preprocessor::EnterMacro(LexerToken &Tok, MacroArgs *Args) {
CurLexer = 0;
CurDirLookup = 0;
CurMacroExpander = new MacroExpander(Tok, Args, *this);
if (NumCachedMacroExpanders == 0) {
CurMacroExpander = new MacroExpander(Tok, Args, *this);
} else {
CurMacroExpander = MacroExpanderCache[--NumCachedMacroExpanders];
CurMacroExpander->Init(Tok, Args);
}
}
/// EnterTokenStream - Add a "macro" context to the top of the include stack,
@ -402,7 +412,12 @@ void Preprocessor::EnterTokenStream(const LexerToken *Toks, unsigned NumToks) {
CurDirLookup = 0;
// Create a macro expander to expand from the specified token stream.
CurMacroExpander = new MacroExpander(Toks, NumToks, *this);
if (NumCachedMacroExpanders == 0) {
CurMacroExpander = new MacroExpander(Toks, NumToks, *this);
} else {
CurMacroExpander = MacroExpanderCache[--NumCachedMacroExpanders];
CurMacroExpander->Init(Toks, NumToks);
}
}
/// RemoveTopOfLexerStack - Pop the current lexer/macro exp off the top of the
@ -410,8 +425,16 @@ void Preprocessor::EnterTokenStream(const LexerToken *Toks, unsigned NumToks) {
/// state of the top-of-stack lexer is known.
void Preprocessor::RemoveTopOfLexerStack() {
assert(!IncludeMacroStack.empty() && "Ran out of stack entries to load");
delete CurLexer;
delete CurMacroExpander;
if (CurMacroExpander) {
// Delete or cache the now-dead macro expander.
if (NumCachedMacroExpanders == MacroExpanderCacheSize)
delete CurMacroExpander;
else
MacroExpanderCache[NumCachedMacroExpanders++] = CurMacroExpander;
} else {
delete CurLexer;
}
CurLexer = IncludeMacroStack.back().TheLexer;
CurDirLookup = IncludeMacroStack.back().TheDirLookup;
CurMacroExpander = IncludeMacroStack.back().TheMacroExpander;
@ -1047,7 +1070,11 @@ bool Preprocessor::HandleEndOfMacro(LexerToken &Result) {
assert(CurMacroExpander && !CurLexer &&
"Ending a macro when currently in a #include file!");
delete CurMacroExpander;
// Delete or cache the now-dead macro expander.
if (NumCachedMacroExpanders == MacroExpanderCacheSize)
delete CurMacroExpander;
else
MacroExpanderCache[NumCachedMacroExpanders++] = CurMacroExpander;
// Handle this like a #include file being popped off the stack.
CurMacroExpander = 0;

View File

@ -141,12 +141,28 @@ class MacroExpander {
public:
/// Create a macro expander for the specified macro with the specified actual
/// arguments. Note that this ctor takes ownership of the ActualArgs pointer.
MacroExpander(LexerToken &Tok, MacroArgs *ActualArgs, Preprocessor &PP);
MacroExpander(LexerToken &Tok, MacroArgs *ActualArgs, Preprocessor &pp)
: Macro(0), ActualArgs(0), PP(pp) {
Init(Tok, ActualArgs);
}
/// Init - Initialize this macro expander to expand from the specified macro
/// with the specified argument information. Note that this ctor takes
/// ownership of the ActualArgs pointer.
void Init(LexerToken &Tok, MacroArgs *ActualArgs);
/// Create a macro expander for the specified token stream. This does not
/// take ownership of the specified token vector.
MacroExpander(const LexerToken *TokArray, unsigned NumToks, Preprocessor &PP);
~MacroExpander();
MacroExpander(const LexerToken *TokArray, unsigned NumToks, Preprocessor &pp)
: Macro(0), ActualArgs(0), PP(pp) {
Init(TokArray, NumToks);
}
/// Init - Initialize this macro expander with the specified token stream.
/// This does not take ownership of the specified token vector.
void Init(const LexerToken *TokArray, unsigned NumToks);
~MacroExpander() { destroy(); }
/// isNextTokenLParen - If the next token lexed will pop this macro off the
/// expansion stack, return 2. If the next unexpanded token is a '(', return
@ -157,6 +173,8 @@ public:
void Lex(LexerToken &Tok);
private:
void destroy();
/// isAtEnd - Return true if the next lex call will pop this macro off the
/// include stack.
bool isAtEnd() const {

View File

@ -114,6 +114,11 @@ class Preprocessor {
unsigned NumMacroExpanded, NumFnMacroExpanded, NumBuiltinMacroExpanded;
unsigned NumFastMacroExpanded, NumTokenPaste, NumFastTokenPaste;
unsigned NumSkipped;
/// MacroExpanderCache - Cache macro expanders to reduce malloc traffic.
enum { MacroExpanderCacheSize = 8 };
unsigned NumCachedMacroExpanders;
MacroExpander *MacroExpanderCache[MacroExpanderCacheSize];
public:
Preprocessor(Diagnostic &diags, const LangOptions &opts, TargetInfo &target,
SourceManager &SM, HeaderSearch &Headers);