diff options
author | Manuel Klimek <klimek@google.com> | 2014-05-21 13:28:59 +0000 |
---|---|---|
committer | Manuel Klimek <klimek@google.com> | 2014-05-21 13:28:59 +0000 |
commit | 95403e6f607cb51a4c23663c80712db2af2a1cff (patch) | |
tree | 5136118541004c88d28d391ebadbffadab5bd65c /clang/lib/AST/ASTContext.cpp | |
parent | 2a958321c8a149b3f4952dc78a8f6edcbcae1996 (diff) | |
download | bcm5719-llvm-95403e6f607cb51a4c23663c80712db2af2a1cff.tar.gz bcm5719-llvm-95403e6f607cb51a4c23663c80712db2af2a1cff.zip |
Make the parent-map use significantly less memory.
On test files I ran this on, memory consumption overall went down from
2.5G to 2G, without performance regressions.
I also investigated making DynTypedNode by itself smaller (by pulling
out pointers for everything that doesn't fit in 8 bytes). This led to
another 200-300MB saved, but also introduced a significant regression in
performance due to the memory management overhead.
llvm-svn: 209297
Diffstat (limited to 'clang/lib/AST/ASTContext.cpp')
-rw-r--r-- | clang/lib/AST/ASTContext.cpp | 40 |
1 files changed, 37 insertions, 3 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 99547f81758..2ea93bae674 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -755,6 +755,8 @@ ASTContext::ASTContext(LangOptions& LOpts, SourceManager &SM, } ASTContext::~ASTContext() { + ReleaseParentMapEntries(); + // Release the DenseMaps associated with DeclContext objects. // FIXME: Is this the ideal solution? ReleaseDeclContextMaps(); @@ -789,6 +791,18 @@ ASTContext::~ASTContext() { llvm::DeleteContainerSeconds(MangleNumberingContexts); } +void ASTContext::ReleaseParentMapEntries() { + if (!AllParents) return; + for (const auto &Entry : *AllParents) { + if (Entry.second.is<ast_type_traits::DynTypedNode *>()) { + delete Entry.second.get<ast_type_traits::DynTypedNode *>(); + } else { + assert(Entry.second.is<ParentVector *>()); + delete Entry.second.get<ParentVector *>(); + } + } +} + void ASTContext::AddDeallocation(void (*Callback)(void*), void *Data) { Deallocations[Callback].push_back(Data); } @@ -8162,7 +8176,7 @@ namespace { bool TraverseNode(T *Node, bool(VisitorBase:: *traverse) (T *)) { if (!Node) return true; - if (ParentStack.size() > 0) + if (ParentStack.size() > 0) { // FIXME: Currently we add the same parent multiple times, for example // when we visit all subexpressions of template instantiations; this is // suboptimal, bug benign: the only way to visit those is with @@ -8171,7 +8185,23 @@ namespace { // map. The main problem there is to implement hash functions / // comparison operators for all types that DynTypedNode supports that // do not have pointer identity. - (*Parents)[Node].push_back(ParentStack.back()); + auto &NodeOrVector = (*Parents)[Node]; + if (NodeOrVector.isNull()) { + NodeOrVector = new ast_type_traits::DynTypedNode(ParentStack.back()); + } else if (NodeOrVector + .template is<ast_type_traits::DynTypedNode *>()) { + auto *Node = + NodeOrVector.template get<ast_type_traits::DynTypedNode *>(); + auto *Vector = new ASTContext::ParentVector(1, *Node); + Vector->push_back(ParentStack.back()); + NodeOrVector = Vector; + delete Node; + } else { + assert(NodeOrVector.template is<ASTContext::ParentVector *>()); + NodeOrVector.template get<ASTContext::ParentVector *>()->push_back( + ParentStack.back()); + } + } ParentStack.push_back(ast_type_traits::DynTypedNode::create(*Node)); bool Result = (this ->* traverse) (Node); ParentStack.pop_back(); @@ -8209,7 +8239,11 @@ ASTContext::getParents(const ast_type_traits::DynTypedNode &Node) { if (I == AllParents->end()) { return ParentVector(); } - return I->second; + if (I->second.is<ast_type_traits::DynTypedNode *>()) { + return ParentVector(1, *I->second.get<ast_type_traits::DynTypedNode *>()); + } + const auto &Parents = *I->second.get<ParentVector *>(); + return ParentVector(Parents.begin(), Parents.end()); } bool |