implement trivial scope caching. This reduces malloc traffic in the common
case, speeding up parsing of this contrived example:
#define A {{}}
#define B A A A A A A A A A A
#define C B B B B B B B B B B
#define D C C C C C C C C C C
#define E D D D D D D D D D D
#define F E E E E E E E E E E
#define G F F F F F F F F F F
#define H G G G G G G G G G G
void foo() {
H
}
from 7.478s to 4.321s. GCC requires 8.2s.
llvm-svn: 39138
diff --git a/clang/Parse/Parser.cpp b/clang/Parse/Parser.cpp
index dc1909a..3e991ba 100644
--- a/clang/Parse/Parser.cpp
+++ b/clang/Parse/Parser.cpp
@@ -37,11 +37,6 @@
ParenCount = BracketCount = BraceCount = 0;
}
-Parser::~Parser() {
- // If we still have scopes active, delete the scope tree.
- delete CurScope;
-}
-
/// Out-of-line virtual destructor to provide home for Action class.
Action::~Action() {}
@@ -186,9 +181,19 @@
// Scope manipulation
//===----------------------------------------------------------------------===//
+/// ScopeCache - Cache scopes to avoid malloc traffic.
+static SmallVector<Scope*, 16> ScopeCache;
+
/// EnterScope - Start a new scope.
void Parser::EnterScope(unsigned ScopeFlags) {
- CurScope = new Scope(CurScope, ScopeFlags);
+ if (!ScopeCache.empty()) {
+ Scope *N = ScopeCache.back();
+ ScopeCache.pop_back();
+ N->Init(CurScope, ScopeFlags);
+ CurScope = N;
+ } else {
+ CurScope = new Scope(CurScope, ScopeFlags);
+ }
}
/// ExitScope - Pop a scope off the scope stack.
@@ -200,7 +205,11 @@
Scope *Old = CurScope;
CurScope = Old->getParent();
- delete Old;
+
+ if (ScopeCache.size() == 16)
+ delete Old;
+ else
+ ScopeCache.push_back(Old);
}
@@ -210,6 +219,17 @@
// C99 6.9: External Definitions.
//===----------------------------------------------------------------------===//
+Parser::~Parser() {
+ // If we still have scopes active, delete the scope tree.
+ delete CurScope;
+
+ // Free the scope cache.
+ while (!ScopeCache.empty()) {
+ delete ScopeCache.back();
+ ScopeCache.pop_back();
+ }
+}
+
/// Initialize - Warm up the parser.
///
void Parser::Initialize() {