diff options
author | Benjamin Kramer <benny.kra@googlemail.com> | 2015-10-23 09:04:55 +0000 |
---|---|---|
committer | Benjamin Kramer <benny.kra@googlemail.com> | 2015-10-23 09:04:55 +0000 |
commit | 94355aeff81696e92e26b6022453611c06204e54 (patch) | |
tree | d546c2e9cd3034ed73ff731fdc8daf135b6bb6ac /clang/lib/AST/ASTContext.cpp | |
parent | cae21e4b4ea2b16b5e31ccabb4e014c67558dfbd (diff) | |
download | bcm5719-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.cpp | 110 |
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) { |