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/Support/Casting.h"
|
||||
#include "clang/Analysis/Support/BumpVector.h"
|
||||
#include "clang/StaticAnalyzer/PathSensitive/GRState.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
|
|
@ -38,7 +39,6 @@ class CFG;
|
|||
|
||||
namespace ento {
|
||||
|
||||
class GRState;
|
||||
class ExplodedGraph;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
@ -115,7 +115,9 @@ class ExplodedNode : public llvm::FoldingSetNode {
|
|||
public:
|
||||
|
||||
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.
|
||||
ProgramPoint getLocation() const { return Location; }
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#include "clang/StaticAnalyzer/PathSensitive/Environment.h"
|
||||
#include "clang/StaticAnalyzer/PathSensitive/Store.h"
|
||||
#include "clang/StaticAnalyzer/PathSensitive/SValBuilder.h"
|
||||
#include "llvm/ADT/PointerIntPair.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/ADT/ImmutableMap.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
|
|
@ -78,7 +79,7 @@ private:
|
|||
|
||||
friend class GRStateManager;
|
||||
|
||||
GRStateManager *StateMgr;
|
||||
llvm::PointerIntPair<GRStateManager *, 1, bool> 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.
|
||||
|
|
@ -92,7 +93,7 @@ public:
|
|||
/// This ctor is used when creating the first GRState object.
|
||||
GRState(GRStateManager *mgr, const Environment& env,
|
||||
Store st, GenericDataMap gdm)
|
||||
: StateMgr(mgr),
|
||||
: stateMgr(mgr, false),
|
||||
Env(env),
|
||||
St(st),
|
||||
GDM(gdm) {}
|
||||
|
|
@ -101,14 +102,23 @@ public:
|
|||
/// in FoldingSetNode will also get copied.
|
||||
GRState(const GRState& RHS)
|
||||
: llvm::FoldingSetNode(),
|
||||
StateMgr(RHS.StateMgr),
|
||||
stateMgr(RHS.stateMgr.getPointer(), false),
|
||||
Env(RHS.Env),
|
||||
St(RHS.St),
|
||||
GDM(RHS.GDM) {}
|
||||
|
||||
/// getStateManager - Return the GRStateManager associated with this state.
|
||||
/// Return the GRStateManager associated with this state.
|
||||
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.
|
||||
|
|
@ -428,9 +438,16 @@ private:
|
|||
/// Object that manages the data for all created SVals.
|
||||
llvm::OwningPtr<SValBuilder> svalBuilder;
|
||||
|
||||
/// Alloc - A BumpPtrAllocator to allocate states.
|
||||
/// A BumpPtrAllocator to allocate states.
|
||||
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:
|
||||
GRStateManager(ASTContext& Ctx,
|
||||
StoreManagerCreator CreateStoreManager,
|
||||
|
|
@ -509,6 +526,10 @@ public:
|
|||
}
|
||||
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -574,6 +574,9 @@ void ExprEngine::processCFGElement(const CFGElement E,
|
|||
}
|
||||
|
||||
void ExprEngine::ProcessStmt(const CFGStmt S, StmtNodeBuilder& builder) {
|
||||
// Recycle any unused states in the GRStateManager.
|
||||
StateMgr.recycleUnusedStates();
|
||||
|
||||
currentStmt = S.getStmt();
|
||||
PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
|
||||
currentStmt->getLocStart(),
|
||||
|
|
|
|||
|
|
@ -285,6 +285,18 @@ const GRState* GRStateManager::getInitialState(const LocationContext *InitLoc) {
|
|||
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) {
|
||||
|
||||
llvm::FoldingSetNodeID ID;
|
||||
|
|
@ -294,10 +306,18 @@ const GRState* GRStateManager::getPersistentState(GRState& State) {
|
|||
if (GRState* I = StateSet.FindNodeOrInsertPos(ID, InsertPos))
|
||||
return I;
|
||||
|
||||
GRState* I = (GRState*) Alloc.Allocate<GRState>();
|
||||
new (I) GRState(State);
|
||||
StateSet.InsertNode(I, InsertPos);
|
||||
return I;
|
||||
GRState *newState = 0;
|
||||
if (!freeStates.empty()) {
|
||||
newState = freeStates.back();
|
||||
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 {
|
||||
|
|
|
|||
Loading…
Reference in New Issue