#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/Support/Casting.h"
#include "clang/Analysis/Support/BumpVector.h"
+#include "clang/StaticAnalyzer/PathSensitive/GRState.h"
namespace clang {
namespace ento {
-class GRState;
class ExplodedGraph;
//===----------------------------------------------------------------------===//
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; }
#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"
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.
/// 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) {}
/// 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.
/// 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,
}
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.
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;
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 {