Recycle memory for GRStates that are never referenced
by ExplodedNodes. This leads to about a 4-8% reduction in memory footprint when analyzing functions in sqlite3. llvm-svn: 124214
This commit is contained in:
		
							parent
							
								
									bcf848f70a
								
							
						
					
					
						commit
						ade45d9703
					
				| 
						 | 
					@ -31,6 +31,7 @@
 | 
				
			||||||
#include "llvm/ADT/DepthFirstIterator.h"
 | 
					#include "llvm/ADT/DepthFirstIterator.h"
 | 
				
			||||||
#include "llvm/Support/Casting.h"
 | 
					#include "llvm/Support/Casting.h"
 | 
				
			||||||
#include "clang/Analysis/Support/BumpVector.h"
 | 
					#include "clang/Analysis/Support/BumpVector.h"
 | 
				
			||||||
 | 
					#include "clang/StaticAnalyzer/PathSensitive/GRState.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace clang {
 | 
					namespace clang {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -38,7 +39,6 @@ class CFG;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace ento {
 | 
					namespace ento {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class GRState;
 | 
					 | 
				
			||||||
class ExplodedGraph;
 | 
					class ExplodedGraph;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//===----------------------------------------------------------------------===//
 | 
					//===----------------------------------------------------------------------===//
 | 
				
			||||||
| 
						 | 
					@ -115,7 +115,9 @@ class ExplodedNode : public llvm::FoldingSetNode {
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  explicit ExplodedNode(const ProgramPoint& loc, const GRState* state)
 | 
					  explicit ExplodedNode(const ProgramPoint& loc, const GRState* state)
 | 
				
			||||||
    : Location(loc), State(state) {}
 | 
					    : Location(loc), State(state) {
 | 
				
			||||||
 | 
					    const_cast<GRState*>(State)->setReferencedByExplodedNode();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// getLocation - Returns the edge associated with the given node.
 | 
					  /// getLocation - Returns the edge associated with the given node.
 | 
				
			||||||
  ProgramPoint getLocation() const { return Location; }
 | 
					  ProgramPoint getLocation() const { return Location; }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,6 +18,7 @@
 | 
				
			||||||
#include "clang/StaticAnalyzer/PathSensitive/Environment.h"
 | 
					#include "clang/StaticAnalyzer/PathSensitive/Environment.h"
 | 
				
			||||||
#include "clang/StaticAnalyzer/PathSensitive/Store.h"
 | 
					#include "clang/StaticAnalyzer/PathSensitive/Store.h"
 | 
				
			||||||
#include "clang/StaticAnalyzer/PathSensitive/SValBuilder.h"
 | 
					#include "clang/StaticAnalyzer/PathSensitive/SValBuilder.h"
 | 
				
			||||||
 | 
					#include "llvm/ADT/PointerIntPair.h"
 | 
				
			||||||
#include "llvm/ADT/FoldingSet.h"
 | 
					#include "llvm/ADT/FoldingSet.h"
 | 
				
			||||||
#include "llvm/ADT/ImmutableMap.h"
 | 
					#include "llvm/ADT/ImmutableMap.h"
 | 
				
			||||||
#include "llvm/Support/Casting.h"
 | 
					#include "llvm/Support/Casting.h"
 | 
				
			||||||
| 
						 | 
					@ -78,7 +79,7 @@ private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  friend class GRStateManager;
 | 
					  friend class GRStateManager;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  GRStateManager *StateMgr;
 | 
					  llvm::PointerIntPair<GRStateManager *, 1, bool> stateMgr;
 | 
				
			||||||
  Environment Env;           // Maps a Stmt to its current SVal.
 | 
					  Environment Env;           // Maps a Stmt to its current SVal.
 | 
				
			||||||
  Store St;                  // Maps a location to its current value.
 | 
					  Store St;                  // Maps a location to its current value.
 | 
				
			||||||
  GenericDataMap   GDM;      // Custom data stored by a client of this class.
 | 
					  GenericDataMap   GDM;      // Custom data stored by a client of this class.
 | 
				
			||||||
| 
						 | 
					@ -92,7 +93,7 @@ public:
 | 
				
			||||||
  /// This ctor is used when creating the first GRState object.
 | 
					  /// This ctor is used when creating the first GRState object.
 | 
				
			||||||
  GRState(GRStateManager *mgr, const Environment& env,
 | 
					  GRState(GRStateManager *mgr, const Environment& env,
 | 
				
			||||||
          Store st, GenericDataMap gdm)
 | 
					          Store st, GenericDataMap gdm)
 | 
				
			||||||
    : StateMgr(mgr),
 | 
					    : stateMgr(mgr, false),
 | 
				
			||||||
      Env(env),
 | 
					      Env(env),
 | 
				
			||||||
      St(st),
 | 
					      St(st),
 | 
				
			||||||
      GDM(gdm) {}
 | 
					      GDM(gdm) {}
 | 
				
			||||||
| 
						 | 
					@ -101,14 +102,23 @@ public:
 | 
				
			||||||
  ///  in FoldingSetNode will also get copied.
 | 
					  ///  in FoldingSetNode will also get copied.
 | 
				
			||||||
  GRState(const GRState& RHS)
 | 
					  GRState(const GRState& RHS)
 | 
				
			||||||
    : llvm::FoldingSetNode(),
 | 
					    : llvm::FoldingSetNode(),
 | 
				
			||||||
      StateMgr(RHS.StateMgr),
 | 
					      stateMgr(RHS.stateMgr.getPointer(), false),
 | 
				
			||||||
      Env(RHS.Env),
 | 
					      Env(RHS.Env),
 | 
				
			||||||
      St(RHS.St),
 | 
					      St(RHS.St),
 | 
				
			||||||
      GDM(RHS.GDM) {}
 | 
					      GDM(RHS.GDM) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// getStateManager - Return the GRStateManager associated with this state.
 | 
					  /// Return the GRStateManager associated with this state.
 | 
				
			||||||
  GRStateManager &getStateManager() const {
 | 
					  GRStateManager &getStateManager() const {
 | 
				
			||||||
    return *StateMgr;
 | 
					    return *stateMgr.getPointer();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Return true if this state is referenced by a persistent ExplodedNode.
 | 
				
			||||||
 | 
					  bool referencedByExplodedNode() const {
 | 
				
			||||||
 | 
					    return stateMgr.getInt();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  void setReferencedByExplodedNode() {
 | 
				
			||||||
 | 
					    stateMgr.setInt(true);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// getEnvironment - Return the environment associated with this state.
 | 
					  /// getEnvironment - Return the environment associated with this state.
 | 
				
			||||||
| 
						 | 
					@ -428,9 +438,16 @@ private:
 | 
				
			||||||
  /// Object that manages the data for all created SVals.
 | 
					  /// Object that manages the data for all created SVals.
 | 
				
			||||||
  llvm::OwningPtr<SValBuilder> svalBuilder;
 | 
					  llvm::OwningPtr<SValBuilder> svalBuilder;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// Alloc - A BumpPtrAllocator to allocate states.
 | 
					  /// A BumpPtrAllocator to allocate states.
 | 
				
			||||||
  llvm::BumpPtrAllocator &Alloc;
 | 
					  llvm::BumpPtrAllocator &Alloc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// A vector of recently allocated GRStates that can potentially be
 | 
				
			||||||
 | 
					  /// reused.
 | 
				
			||||||
 | 
					  std::vector<GRState *> recentlyAllocatedStates;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /// A vector of GRStates that we can reuse.
 | 
				
			||||||
 | 
					  std::vector<GRState *> freeStates;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
  GRStateManager(ASTContext& Ctx,
 | 
					  GRStateManager(ASTContext& Ctx,
 | 
				
			||||||
                 StoreManagerCreator CreateStoreManager,
 | 
					                 StoreManagerCreator CreateStoreManager,
 | 
				
			||||||
| 
						 | 
					@ -510,6 +527,10 @@ public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const GRState* getPersistentState(GRState& Impl);
 | 
					  const GRState* getPersistentState(GRState& Impl);
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
 | 
					  /// Periodically called by ExprEngine to recycle GRStates that were
 | 
				
			||||||
 | 
					  /// created but never used for creating an ExplodedNode.
 | 
				
			||||||
 | 
					  void recycleUnusedStates();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  //==---------------------------------------------------------------------==//
 | 
					  //==---------------------------------------------------------------------==//
 | 
				
			||||||
  // Generic Data Map methods.
 | 
					  // Generic Data Map methods.
 | 
				
			||||||
  //==---------------------------------------------------------------------==//
 | 
					  //==---------------------------------------------------------------------==//
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -574,6 +574,9 @@ void ExprEngine::processCFGElement(const CFGElement E,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ExprEngine::ProcessStmt(const CFGStmt S, StmtNodeBuilder& builder) {
 | 
					void ExprEngine::ProcessStmt(const CFGStmt S, StmtNodeBuilder& builder) {
 | 
				
			||||||
 | 
					  // Recycle any unused states in the GRStateManager.
 | 
				
			||||||
 | 
					  StateMgr.recycleUnusedStates();
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
  currentStmt = S.getStmt();
 | 
					  currentStmt = S.getStmt();
 | 
				
			||||||
  PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
 | 
					  PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
 | 
				
			||||||
                                currentStmt->getLocStart(),
 | 
					                                currentStmt->getLocStart(),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -285,6 +285,18 @@ const GRState* GRStateManager::getInitialState(const LocationContext *InitLoc) {
 | 
				
			||||||
  return getPersistentState(State);
 | 
					  return getPersistentState(State);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void GRStateManager::recycleUnusedStates() {
 | 
				
			||||||
 | 
					  for (std::vector<GRState*>::iterator i = recentlyAllocatedStates.begin(),
 | 
				
			||||||
 | 
					       e = recentlyAllocatedStates.end(); i != e; ++i) {
 | 
				
			||||||
 | 
					    GRState *state = *i;
 | 
				
			||||||
 | 
					    if (state->referencedByExplodedNode())
 | 
				
			||||||
 | 
					      continue;
 | 
				
			||||||
 | 
					    StateSet.RemoveNode(state);
 | 
				
			||||||
 | 
					    freeStates.push_back(state);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  recentlyAllocatedStates.clear();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const GRState* GRStateManager::getPersistentState(GRState& State) {
 | 
					const GRState* GRStateManager::getPersistentState(GRState& State) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  llvm::FoldingSetNodeID ID;
 | 
					  llvm::FoldingSetNodeID ID;
 | 
				
			||||||
| 
						 | 
					@ -294,10 +306,18 @@ const GRState* GRStateManager::getPersistentState(GRState& State) {
 | 
				
			||||||
  if (GRState* I = StateSet.FindNodeOrInsertPos(ID, InsertPos))
 | 
					  if (GRState* I = StateSet.FindNodeOrInsertPos(ID, InsertPos))
 | 
				
			||||||
    return I;
 | 
					    return I;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  GRState* I = (GRState*) Alloc.Allocate<GRState>();
 | 
					  GRState *newState = 0;
 | 
				
			||||||
  new (I) GRState(State);
 | 
					  if (!freeStates.empty()) {
 | 
				
			||||||
  StateSet.InsertNode(I, InsertPos);
 | 
					    newState = freeStates.back();
 | 
				
			||||||
  return I;
 | 
					    freeStates.pop_back();    
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else {
 | 
				
			||||||
 | 
					    newState = (GRState*) Alloc.Allocate<GRState>();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  new (newState) GRState(State);
 | 
				
			||||||
 | 
					  StateSet.InsertNode(newState, InsertPos);
 | 
				
			||||||
 | 
					  recentlyAllocatedStates.push_back(newState);
 | 
				
			||||||
 | 
					  return newState;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const GRState* GRState::makeWithStore(Store store) const {
 | 
					const GRState* GRState::makeWithStore(Store store) const {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue