[PATCH] Implements memoization for ancestor matching.
Manuel Klimek
klimek at google.com
Fri Mar 8 14:18:58 PST 2013
Hi djasper,
This yields a log(#ast_nodes) improvement with matchers like
stmt(unless(hasAncestor(...))).
http://llvm-reviews.chandlerc.com/D510
Files:
lib/ASTMatchers/ASTMatchFinder.cpp
Index: lib/ASTMatchers/ASTMatchFinder.cpp
===================================================================
--- lib/ASTMatchers/ASTMatchFinder.cpp
+++ lib/ASTMatchers/ASTMatchFinder.cpp
@@ -388,7 +388,8 @@
const DynTypedMatcher &Matcher,
BoundNodesTreeBuilder *Builder,
AncestorMatchMode MatchMode) {
- return matchesAncestorOfRecursively(Node, Matcher, Builder, MatchMode);
+ return memoizedMatchesAncestorOfRecursively(Node, Matcher, Builder,
+ MatchMode);
}
// Matches all registered matchers on the given node and calls the
@@ -421,15 +422,36 @@
bool shouldUseDataRecursionFor(clang::Stmt *S) const { return false; }
private:
- bool matchesAncestorOfRecursively(
+ bool memoizedMatchesAncestorOfRecursively(
const ast_type_traits::DynTypedNode &Node, const DynTypedMatcher &Matcher,
BoundNodesTreeBuilder *Builder, AncestorMatchMode MatchMode) {
if (Node.get<TranslationUnitDecl>() ==
ActiveASTContext->getTranslationUnitDecl())
return false;
assert(Node.getMemoizationData() &&
"Invariant broken: only nodes that support memoization may be "
"used in the parent map.");
+ const UntypedMatchInput input(Matcher.getID(), Node.getMemoizationData());
+
+ MemoizationMap::iterator I = ResultCache.find(input);
+ if (I == ResultCache.end()) {
+ BoundNodesTreeBuilder AncestorBoundNodesBuilder;
+ bool Matches = matchesAncestorOfRecursively(
+ Node, Matcher, &AncestorBoundNodesBuilder, MatchMode);
+ // Note that we cannot insert before the recursive call and keep the
+ // iterator as DenseMap invalidates iterators on insert.
+ I = ResultCache.insert(std::make_pair(input, MemoizedMatchResult()))
+ .first;
+ I->second.Nodes = AncestorBoundNodesBuilder.build();
+ I->second.ResultOfMatch = Matches;
+ }
+ I->second.Nodes.copyTo(Builder);
+ return I->second.ResultOfMatch;
+ }
+
+ bool matchesAncestorOfRecursively(
+ const ast_type_traits::DynTypedNode &Node, const DynTypedMatcher &Matcher,
+ BoundNodesTreeBuilder *Builder, AncestorMatchMode MatchMode) {
ASTContext::ParentVector Parents = ActiveASTContext->getParents(Node);
if (Parents.empty()) {
assert(false && "Found node that is not in the parent map.");
@@ -446,13 +468,13 @@
for (ASTContext::ParentVector::const_iterator AncestorI = Parents.begin(),
AncestorE = Parents.end();
AncestorI != AncestorE; ++AncestorI) {
- if (matchesAncestorOfRecursively(*AncestorI, Matcher, Builder, MatchMode))
+ if (memoizedMatchesAncestorOfRecursively(*AncestorI, Matcher, Builder,
+ MatchMode))
return true;
}
return false;
}
-
// Implements a BoundNodesTree::Visitor that calls a MatchCallback with
// the aggregated bound nodes for each match.
class MatchVisitor : public BoundNodesTree::Visitor {
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D510.1.patch
Type: text/x-patch
Size: 3138 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130308/d0025831/attachment.bin>
More information about the cfe-commits
mailing list