From 75e45641402bf5a7766206c52fde2d6f93e584f6 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Thu, 10 Feb 2011 02:21:52 +0000 Subject: [PATCH] static analyzer: Make GRStates reference counted, with reference counts managed by ExplodedNodes. This reduces memory usage of the analyzer on sqlite by another 5%. llvm-svn: 125260 --- .../Core/PathSensitive/ExplodedGraph.h | 6 +++- .../Core/PathSensitive/GRState.h | 36 +++++++++++-------- .../lib/StaticAnalyzer/Core/ExplodedGraph.cpp | 2 ++ 3 files changed, 28 insertions(+), 16 deletions(-) diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h index e1cc6fd63017..e5d6876fa6b2 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h @@ -118,7 +118,11 @@ public: explicit ExplodedNode(const ProgramPoint& loc, const GRState* state) : Location(loc), State(state) { - const_cast(State)->setReferencedByExplodedNode(); + const_cast(State)->incrementReferenceCount(); + } + + ~ExplodedNode() { + const_cast(State)->decrementReferenceCount(); } /// getLocation - Returns the edge associated with the given node. diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/GRState.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/GRState.h index 3e34e69e5aa2..a2cbb20e7b1b 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/GRState.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/GRState.h @@ -79,11 +79,13 @@ private: friend class GRStateManager; friend class ExplodedGraph; + friend class ExplodedNode; - llvm::PointerIntPair stateMgr; + GRStateManager *stateMgr; Environment Env; // Maps a Stmt to its current SVal. Store St; // Maps a location to its current value. GenericDataMap GDM; // Custom data stored by a client of this class. + unsigned refCount; /// makeWithStore - Return a GRState with the same values as the current /// state with the exception of using the specified Store. @@ -94,33 +96,27 @@ public: /// This ctor is used when creating the first GRState object. GRState(GRStateManager *mgr, const Environment& env, Store st, GenericDataMap gdm) - : stateMgr(mgr, false), + : stateMgr(mgr), Env(env), St(st), - GDM(gdm) {} + GDM(gdm), + refCount(0) {} /// Copy ctor - We must explicitly define this or else the "Next" ptr /// in FoldingSetNode will also get copied. GRState(const GRState& RHS) : llvm::FoldingSetNode(), - stateMgr(RHS.stateMgr.getPointer(), false), + stateMgr(RHS.stateMgr), Env(RHS.Env), St(RHS.St), - GDM(RHS.GDM) {} + GDM(RHS.GDM), + refCount(0) {} /// Return the GRStateManager associated with this state. - GRStateManager &getStateManager() const { - return *stateMgr.getPointer(); - } + GRStateManager &getStateManager() const { return *stateMgr; } /// Return true if this state is referenced by a persistent ExplodedNode. - bool referencedByExplodedNode() const { - return stateMgr.getInt(); - } - - void setReferencedByExplodedNode() { - stateMgr.setInt(true); - } + bool referencedByExplodedNode() const { return refCount > 0; } /// getEnvironment - Return the environment associated with this state. /// The environment is the mapping from expressions to values. @@ -373,6 +369,16 @@ public: void printStdErr(CFG &C) const; void printDOT(llvm::raw_ostream& Out, CFG &C) const; + +private: + /// Increments the number of times this state is referenced by ExplodeNodes. + void incrementReferenceCount() { ++refCount; } + + /// Decrement the number of times this state is referenced by ExplodeNodes. + void decrementReferenceCount() { + assert(refCount > 0); + --refCount; + } }; class GRStateSet { diff --git a/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp b/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp index 84fcacab63a6..3ce50d653919 100644 --- a/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp @@ -123,6 +123,8 @@ void ExplodedGraph::reclaimRecentlyAllocatedNodes() { freeNodes = new NodeList(); getNodeList(freeNodes)->push_back(node); Nodes.RemoveNode(node); + --NumNodes; + node->~ExplodedNode(); } nl.clear();