forked from OSchip/llvm-project
Convert ProgramStateRef to a smart pointer for managing the reference counts of ProgramStates. This leads to a slight memory
improvement, and a simplification of the logic for managing ProgramState objects. llvm-svn: 149311
This commit is contained in:
parent
13a4487f4d
commit
b1ca33fde5
|
@ -119,14 +119,11 @@ public:
|
|||
explicit ExplodedNode(const ProgramPoint &loc, ProgramStateRef state,
|
||||
bool IsSink)
|
||||
: Location(loc), State(state) {
|
||||
const_cast<ProgramState*>(State)->incrementReferenceCount();
|
||||
if (IsSink)
|
||||
Succs.setFlag();
|
||||
}
|
||||
|
||||
~ExplodedNode() {
|
||||
const_cast<ProgramState*>(State)->decrementReferenceCount();
|
||||
}
|
||||
~ExplodedNode() {}
|
||||
|
||||
/// getLocation - Returns the edge associated with the given node.
|
||||
ProgramPoint getLocation() const { return Location; }
|
||||
|
@ -156,7 +153,7 @@ public:
|
|||
ProgramStateRef state,
|
||||
bool IsSink) {
|
||||
ID.Add(Loc);
|
||||
ID.AddPointer(state);
|
||||
ID.AddPointer(state.getPtr());
|
||||
ID.AddBoolean(IsSink);
|
||||
}
|
||||
|
||||
|
|
|
@ -93,7 +93,6 @@ private:
|
|||
void setStore(const StoreRef &storeRef);
|
||||
|
||||
public:
|
||||
|
||||
/// This ctor is used when creating the first ProgramState object.
|
||||
ProgramState(ProgramStateManager *mgr, const Environment& env,
|
||||
StoreRef st, GenericDataMap gdm);
|
||||
|
@ -107,9 +106,6 @@ public:
|
|||
/// Return the ProgramStateManager associated with this state.
|
||||
ProgramStateManager &getStateManager() const { return *stateMgr; }
|
||||
|
||||
/// Return true if this state is referenced by a persistent ExplodedNode.
|
||||
bool referencedByExplodedNode() const { return refCount > 0; }
|
||||
|
||||
/// getEnvironment - Return the environment associated with this state.
|
||||
/// The environment is the mapping from expressions to values.
|
||||
const Environment& getEnvironment() const { return Env; }
|
||||
|
@ -127,7 +123,7 @@ public:
|
|||
/// Profile - Profile the contents of a ProgramState object for use in a
|
||||
/// FoldingSet. Two ProgramState objects are considered equal if they
|
||||
/// have the same Environment, Store, and GenericDataMap.
|
||||
static void Profile(llvm::FoldingSetNodeID& ID, ProgramStateRef V) {
|
||||
static void Profile(llvm::FoldingSetNodeID& ID, const ProgramState *V) {
|
||||
V->Env.Profile(ID);
|
||||
ID.AddPointer(V->store);
|
||||
V->GDM.Profile(ID);
|
||||
|
@ -376,14 +372,8 @@ public:
|
|||
void dumpTaint() 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;
|
||||
}
|
||||
friend void ProgramStateRetain(const ProgramState *state);
|
||||
friend void ProgramStateRelease(const ProgramState *state);
|
||||
|
||||
ProgramStateRef
|
||||
invalidateRegionsImpl(ArrayRef<const MemRegion *> Regions,
|
||||
|
@ -392,45 +382,13 @@ private:
|
|||
const CallOrObjCMessage *Call) const;
|
||||
};
|
||||
|
||||
class ProgramStateSet {
|
||||
typedef llvm::SmallPtrSet<ProgramStateRef,5> ImplTy;
|
||||
ImplTy Impl;
|
||||
public:
|
||||
ProgramStateSet() {}
|
||||
|
||||
inline void Add(ProgramStateRef St) {
|
||||
Impl.insert(St);
|
||||
}
|
||||
|
||||
typedef ImplTy::const_iterator iterator;
|
||||
|
||||
inline unsigned size() const { return Impl.size(); }
|
||||
inline bool empty() const { return Impl.empty(); }
|
||||
|
||||
inline iterator begin() const { return Impl.begin(); }
|
||||
inline iterator end() const { return Impl.end(); }
|
||||
|
||||
class AutoPopulate {
|
||||
ProgramStateSet &S;
|
||||
unsigned StartSize;
|
||||
ProgramStateRef St;
|
||||
public:
|
||||
AutoPopulate(ProgramStateSet &s, ProgramStateRef st)
|
||||
: S(s), StartSize(S.size()), St(st) {}
|
||||
|
||||
~AutoPopulate() {
|
||||
if (StartSize == S.size())
|
||||
S.Add(St);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ProgramStateManager - Factory object for ProgramStates.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class ProgramStateManager {
|
||||
friend class ProgramState;
|
||||
friend void ProgramStateRelease(const ProgramState *state);
|
||||
private:
|
||||
/// Eng - The SubEngine that owns this state manager.
|
||||
SubEngine *Eng; /* Can be null. */
|
||||
|
@ -453,10 +411,6 @@ private:
|
|||
|
||||
/// A BumpPtrAllocator to allocate states.
|
||||
llvm::BumpPtrAllocator &Alloc;
|
||||
|
||||
/// A vector of recently allocated ProgramStates that can potentially be
|
||||
/// reused.
|
||||
std::vector<ProgramState *> recentlyAllocatedStates;
|
||||
|
||||
/// A vector of ProgramStates that we can reuse.
|
||||
std::vector<ProgramState *> freeStates;
|
||||
|
@ -563,10 +517,6 @@ public:
|
|||
return S1->store == S2->store;
|
||||
}
|
||||
|
||||
/// Periodically called by ExprEngine to recycle ProgramStates that were
|
||||
/// created but never used for creating an ExplodedNode.
|
||||
void recycleUnusedStates();
|
||||
|
||||
//==---------------------------------------------------------------------==//
|
||||
// Generic Data Map methods.
|
||||
//==---------------------------------------------------------------------==//
|
||||
|
|
|
@ -10,11 +10,31 @@
|
|||
#ifndef LLVM_CLANG_PROGRAMSTATE_FWD_H
|
||||
#define LLVM_CLANG_PROGRAMSTATE_FWD_H
|
||||
|
||||
#include "llvm/ADT/IntrusiveRefCntPtr.h"
|
||||
|
||||
namespace clang {
|
||||
namespace ento {
|
||||
class ProgramState;
|
||||
class ProgramStateManager;
|
||||
typedef const ProgramState* ProgramStateRef;
|
||||
void ProgramStateRetain(const ProgramState *state);
|
||||
void ProgramStateRelease(const ProgramState *state);
|
||||
}
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
template <> struct IntrusiveRefCntPtrInfo<const clang::ento::ProgramState> {
|
||||
static void retain(const clang::ento::ProgramState *state) {
|
||||
clang::ento::ProgramStateRetain(state);
|
||||
}
|
||||
static void release(const clang::ento::ProgramState *state) {
|
||||
clang::ento::ProgramStateRelease(state);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace clang {
|
||||
namespace ento {
|
||||
typedef llvm::IntrusiveRefCntPtr<const ProgramState> ProgramStateRef;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
|
||||
#include "clang/StaticAnalyzer/Core/Checker.h"
|
||||
|
||||
using namespace clang;
|
||||
|
|
|
@ -238,13 +238,8 @@ static bool shouldRemoveDeadBindings(AnalysisManager &AMgr,
|
|||
|
||||
void ExprEngine::ProcessStmt(const CFGStmt S,
|
||||
ExplodedNode *Pred) {
|
||||
// TODO: Use RAII to remove the unnecessary, tagged nodes.
|
||||
//RegisterCreatedNodes registerCreatedNodes(getGraph());
|
||||
|
||||
// Reclaim any unnecessary nodes in the ExplodedGraph.
|
||||
G.reclaimRecentlyAllocatedNodes();
|
||||
// Recycle any unused states in the ProgramStateManager.
|
||||
StateMgr.recycleUnusedStates();
|
||||
|
||||
currentStmt = S.getStmt();
|
||||
PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
|
||||
|
@ -1856,7 +1851,7 @@ struct DOTGraphTraits<ExplodedNode*> :
|
|||
}
|
||||
|
||||
ProgramStateRef state = N->getState();
|
||||
Out << "\\|StateID: " << (void*) state
|
||||
Out << "\\|StateID: " << (void*) state.getPtr()
|
||||
<< " NodeID: " << (void*) N << "\\|";
|
||||
state->printDOT(Out);
|
||||
|
||||
|
|
|
@ -25,6 +25,26 @@ using namespace ento;
|
|||
// FIXME: Move this elsewhere.
|
||||
ConstraintManager::~ConstraintManager() {}
|
||||
|
||||
namespace clang { namespace ento {
|
||||
/// Increments the number of times this state is referenced.
|
||||
|
||||
void ProgramStateRetain(const ProgramState *state) {
|
||||
++const_cast<ProgramState*>(state)->refCount;
|
||||
}
|
||||
|
||||
/// Decrement the number of times this state is referenced.
|
||||
void ProgramStateRelease(const ProgramState *state) {
|
||||
assert(state->refCount > 0);
|
||||
ProgramState *s = const_cast<ProgramState*>(state);
|
||||
if (--s->refCount == 0) {
|
||||
ProgramStateManager &Mgr = s->getStateManager();
|
||||
Mgr.StateSet.RemoveNode(s);
|
||||
s->~ProgramState();
|
||||
Mgr.freeStates.push_back(s);
|
||||
}
|
||||
}
|
||||
}}
|
||||
|
||||
ProgramState::ProgramState(ProgramStateManager *mgr, const Environment& env,
|
||||
StoreRef st, GenericDataMap gdm)
|
||||
: stateMgr(mgr),
|
||||
|
@ -328,23 +348,10 @@ ProgramStateRef ProgramStateManager::getInitialState(const LocationContext *Init
|
|||
return getPersistentState(State);
|
||||
}
|
||||
|
||||
void ProgramStateManager::recycleUnusedStates() {
|
||||
for (std::vector<ProgramState*>::iterator i = recentlyAllocatedStates.begin(),
|
||||
e = recentlyAllocatedStates.end(); i != e; ++i) {
|
||||
ProgramState *state = *i;
|
||||
if (state->referencedByExplodedNode())
|
||||
continue;
|
||||
StateSet.RemoveNode(state);
|
||||
freeStates.push_back(state);
|
||||
state->~ProgramState();
|
||||
}
|
||||
recentlyAllocatedStates.clear();
|
||||
}
|
||||
|
||||
ProgramStateRef ProgramStateManager::getPersistentStateWithGDM(
|
||||
ProgramStateRef FromState,
|
||||
ProgramStateRef GDMState) {
|
||||
ProgramState NewState = *FromState;
|
||||
ProgramState NewState(*FromState);
|
||||
NewState.GDM = GDMState->GDM;
|
||||
return getPersistentState(NewState);
|
||||
}
|
||||
|
@ -368,12 +375,11 @@ ProgramStateRef ProgramStateManager::getPersistentState(ProgramState &State) {
|
|||
}
|
||||
new (newState) ProgramState(State);
|
||||
StateSet.InsertNode(newState, InsertPos);
|
||||
recentlyAllocatedStates.push_back(newState);
|
||||
return newState;
|
||||
}
|
||||
|
||||
ProgramStateRef ProgramState::makeWithStore(const StoreRef &store) const {
|
||||
ProgramState NewSt = *this;
|
||||
ProgramState NewSt(*this);
|
||||
NewSt.setStore(store);
|
||||
return getStateManager().getPersistentState(NewSt);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue