summaryrefslogtreecommitdiffstats
path: root/clang/lib/AST/ASTContext.cpp
diff options
context:
space:
mode:
authorBenjamin Kramer <benny.kra@googlemail.com>2015-10-23 09:04:55 +0000
committerBenjamin Kramer <benny.kra@googlemail.com>2015-10-23 09:04:55 +0000
commit94355aeff81696e92e26b6022453611c06204e54 (patch)
treed546c2e9cd3034ed73ff731fdc8daf135b6bb6ac /clang/lib/AST/ASTContext.cpp
parentcae21e4b4ea2b16b5e31ccabb4e014c67558dfbd (diff)
downloadbcm5719-llvm-94355aeff81696e92e26b6022453611c06204e54.tar.gz
bcm5719-llvm-94355aeff81696e92e26b6022453611c06204e54.zip
[AST] Re-add TypeLocs and NestedNameSpecifierLocs to the ParentMap.
This relands r250831 after some fixes to shrink the ParentMap overall with one addtional tweak: nodes with pointer identity (e.g. Decl* and friends) can be store more efficiently so I put them in a separate map. All other nodes (so far only TypeLoc and NNSLoc) go in a different map keyed on DynTypedNode. This further uglifies the code but significantly reduces memory overhead. Overall this change still make ParentMap significantly larger but it's nowhere as bad as before. I see about 25 MB over baseline (pre-r251008) on X86ISelLowering.cpp. If this becomes an issue we could consider splitting the maps further as DynTypedNode is still larger (32 bytes) than a single TypeLoc (16 bytes) but I didn't want to introduce even more complexity now. Differential Revision: http://reviews.llvm.org/D14011 llvm-svn: 251101
Diffstat (limited to 'clang/lib/AST/ASTContext.cpp')
-rw-r--r--clang/lib/AST/ASTContext.cpp110
1 files changed, 80 insertions, 30 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index e774e115344..90f9dbbb4a1 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -793,8 +793,15 @@ ASTContext::~ASTContext() {
}
void ASTContext::ReleaseParentMapEntries() {
- if (!AllParents) return;
- for (const auto &Entry : *AllParents) {
+ if (!PointerParents) return;
+ for (const auto &Entry : *PointerParents) {
+ if (Entry.second.is<ast_type_traits::DynTypedNode *>()) {
+ delete Entry.second.get<ast_type_traits::DynTypedNode *>();
+ } else if (Entry.second.is<ParentVector *>()) {
+ delete Entry.second.get<ParentVector *>();
+ }
+ }
+ for (const auto &Entry : *OtherParents) {
if (Entry.second.is<ast_type_traits::DynTypedNode *>()) {
delete Entry.second.get<ast_type_traits::DynTypedNode *>();
} else if (Entry.second.is<ParentVector *>()) {
@@ -8670,8 +8677,8 @@ bool ASTContext::AtomicUsesUnsupportedLibcall(const AtomicExpr *E) const {
namespace {
-ast_type_traits::DynTypedNode
-getSingleDynTypedNodeFromParentMap(ASTContext::ParentMap::mapped_type U) {
+ast_type_traits::DynTypedNode getSingleDynTypedNodeFromParentMap(
+ ASTContext::ParentMapPointers::mapped_type U) {
if (const auto *D = U.dyn_cast<const Decl *>())
return ast_type_traits::DynTypedNode::create(*D);
if (const auto *S = U.dyn_cast<const Stmt *>())
@@ -8679,6 +8686,23 @@ getSingleDynTypedNodeFromParentMap(ASTContext::ParentMap::mapped_type U) {
return *U.get<ast_type_traits::DynTypedNode *>();
}
+/// Template specializations to abstract away from pointers and TypeLocs.
+/// @{
+template <typename T>
+ast_type_traits::DynTypedNode createDynTypedNode(const T &Node) {
+ return ast_type_traits::DynTypedNode::create(*Node);
+}
+template <>
+ast_type_traits::DynTypedNode createDynTypedNode(const TypeLoc &Node) {
+ return ast_type_traits::DynTypedNode::create(Node);
+}
+template <>
+ast_type_traits::DynTypedNode
+createDynTypedNode(const NestedNameSpecifierLoc &Node) {
+ return ast_type_traits::DynTypedNode::create(Node);
+}
+/// @}
+
/// \brief A \c RecursiveASTVisitor that builds a map from nodes to their
/// parents as defined by the \c RecursiveASTVisitor.
///
@@ -8693,17 +8717,21 @@ getSingleDynTypedNodeFromParentMap(ASTContext::ParentMap::mapped_type U) {
/// \brief Builds and returns the translation unit's parent map.
///
/// The caller takes ownership of the returned \c ParentMap.
- static ASTContext::ParentMap *buildMap(TranslationUnitDecl &TU) {
- ParentMapASTVisitor Visitor(new ASTContext::ParentMap);
+ static std::pair<ASTContext::ParentMapPointers *,
+ ASTContext::ParentMapOtherNodes *>
+ buildMap(TranslationUnitDecl &TU) {
+ ParentMapASTVisitor Visitor(new ASTContext::ParentMapPointers,
+ new ASTContext::ParentMapOtherNodes);
Visitor.TraverseDecl(&TU);
- return Visitor.Parents;
+ return std::make_pair(Visitor.Parents, Visitor.OtherParents);
}
private:
typedef RecursiveASTVisitor<ParentMapASTVisitor> VisitorBase;
- ParentMapASTVisitor(ASTContext::ParentMap *Parents) : Parents(Parents) {
- }
+ ParentMapASTVisitor(ASTContext::ParentMapPointers *Parents,
+ ASTContext::ParentMapOtherNodes *OtherParents)
+ : Parents(Parents), OtherParents(OtherParents) {}
bool shouldVisitTemplateInstantiations() const {
return true;
@@ -8717,8 +8745,9 @@ getSingleDynTypedNodeFromParentMap(ASTContext::ParentMap::mapped_type U) {
return false;
}
- template <typename T>
- bool TraverseNode(T *Node, bool(VisitorBase:: *traverse) (T *)) {
+ template <typename T, typename MapNodeTy, typename MapTy>
+ bool TraverseNode(T Node, MapNodeTy MapNode,
+ bool (VisitorBase::*traverse)(T), MapTy *Parents) {
if (!Node)
return true;
if (ParentStack.size() > 0) {
@@ -8732,7 +8761,7 @@ getSingleDynTypedNodeFromParentMap(ASTContext::ParentMap::mapped_type U) {
// map. The main problem there is to implement hash functions /
// comparison operators for all types that DynTypedNode supports that
// do not have pointer identity.
- auto &NodeOrVector = (*Parents)[Node];
+ auto &NodeOrVector = (*Parents)[MapNode];
if (NodeOrVector.isNull()) {
if (const auto *D = ParentStack.back().get<Decl>())
NodeOrVector = D;
@@ -8765,21 +8794,36 @@ getSingleDynTypedNodeFromParentMap(ASTContext::ParentMap::mapped_type U) {
Vector->push_back(ParentStack.back());
}
}
- ParentStack.push_back(ast_type_traits::DynTypedNode::create(*Node));
+ ParentStack.push_back(createDynTypedNode(Node));
bool Result = (this ->* traverse) (Node);
ParentStack.pop_back();
return Result;
}
bool TraverseDecl(Decl *DeclNode) {
- return TraverseNode(DeclNode, &VisitorBase::TraverseDecl);
+ return TraverseNode(DeclNode, DeclNode, &VisitorBase::TraverseDecl,
+ Parents);
}
bool TraverseStmt(Stmt *StmtNode) {
- return TraverseNode(StmtNode, &VisitorBase::TraverseStmt);
+ return TraverseNode(StmtNode, StmtNode, &VisitorBase::TraverseStmt,
+ Parents);
+ }
+
+ bool TraverseTypeLoc(TypeLoc TypeLocNode) {
+ return TraverseNode(TypeLocNode,
+ ast_type_traits::DynTypedNode::create(TypeLocNode),
+ &VisitorBase::TraverseTypeLoc, OtherParents);
}
- ASTContext::ParentMap *Parents;
+ bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSLocNode) {
+ return TraverseNode(
+ NNSLocNode, ast_type_traits::DynTypedNode::create(NNSLocNode),
+ &VisitorBase::TraverseNestedNameSpecifierLoc, OtherParents);
+ }
+
+ ASTContext::ParentMapPointers *Parents;
+ ASTContext::ParentMapOtherNodes *OtherParents;
llvm::SmallVector<ast_type_traits::DynTypedNode, 16> ParentStack;
friend class RecursiveASTVisitor<ParentMapASTVisitor>;
@@ -8787,27 +8831,33 @@ getSingleDynTypedNodeFromParentMap(ASTContext::ParentMap::mapped_type U) {
} // end namespace
-ASTContext::DynTypedNodeList
-ASTContext::getParents(const ast_type_traits::DynTypedNode &Node) {
- assert(Node.getMemoizationData() &&
- "Invariant broken: only nodes that support memoization may be "
- "used in the parent map.");
- if (!AllParents) {
- // We always need to run over the whole translation unit, as
- // hasAncestor can escape any subtree.
- AllParents.reset(
- ParentMapASTVisitor::buildMap(*getTranslationUnitDecl()));
- }
- ParentMap::const_iterator I = AllParents->find(Node.getMemoizationData());
- if (I == AllParents->end()) {
+template <typename NodeTy, typename MapTy>
+static ASTContext::DynTypedNodeList getDynNodeFromMap(const NodeTy &Node,
+ const MapTy &Map) {
+ auto I = Map.find(Node);
+ if (I == Map.end()) {
return llvm::ArrayRef<ast_type_traits::DynTypedNode>();
}
- if (auto *V = I->second.dyn_cast<ParentVector *>()) {
+ if (auto *V = I->second.template dyn_cast<ASTContext::ParentVector *>()) {
return llvm::makeArrayRef(*V);
}
return getSingleDynTypedNodeFromParentMap(I->second);
}
+ASTContext::DynTypedNodeList
+ASTContext::getParents(const ast_type_traits::DynTypedNode &Node) {
+ if (!PointerParents) {
+ // We always need to run over the whole translation unit, as
+ // hasAncestor can escape any subtree.
+ auto Maps = ParentMapASTVisitor::buildMap(*getTranslationUnitDecl());
+ PointerParents.reset(Maps.first);
+ OtherParents.reset(Maps.second);
+ }
+ if (Node.getNodeKind().hasPointerIdentity())
+ return getDynNodeFromMap(Node.getMemoizationData(), *PointerParents);
+ return getDynNodeFromMap(Node, *OtherParents);
+}
+
bool
ASTContext::ObjCMethodsAreEqual(const ObjCMethodDecl *MethodDecl,
const ObjCMethodDecl *MethodImpl) {
OpenPOWER on IntegriCloud