]> granicus.if.org Git - clang/commitdiff
Convert ProgramStateRef to a smart pointer for managing the reference counts of Progr...
authorTed Kremenek <kremenek@apple.com>
Tue, 31 Jan 2012 00:57:20 +0000 (00:57 +0000)
committerTed Kremenek <kremenek@apple.com>
Tue, 31 Jan 2012 00:57:20 +0000 (00:57 +0000)
improvement, and a simplification of the logic for managing ProgramState objects.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@149311 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h
lib/StaticAnalyzer/Core/Checker.cpp
lib/StaticAnalyzer/Core/ExprEngine.cpp
lib/StaticAnalyzer/Core/ProgramState.cpp

index 916babc98b7eb3d958a43c8c8880992ef96edbe2..623fce1472ab68a49c238b5f90ae9d060477ad1d 100644 (file)
@@ -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);
   }
 
index a3e1830be3e5ed2a315ada8a92f84fe984dc472e..f19520984e277e1da583941c61aa692c797bd2fb 100644 (file)
@@ -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.
   //==---------------------------------------------------------------------==//
index c5889088043308e56eaa2928fd123a3a2d88ea2e..5839ad9382560165aac20dfcc16fc3b4e20ac123 100644 (file)
 #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;
 }
 }
 
index f793c7fe29dfb4d73d0c9d582bd4df42c7ae2f36..07e0aac2d4298dc68ee2fdf02cfd344382cae76d 100644 (file)
@@ -11,6 +11,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
 #include "clang/StaticAnalyzer/Core/Checker.h"
 
 using namespace clang;
index 2d047d2c46303030f56cb7eac3028fdd9f8a04e8..5087ae1d3386bca670884c30f7ba86650c034c52 100644 (file)
@@ -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);
 
index b8b9ad94df37993ee030f1a43a03bccc8bbf1863..459bf83ce5ef7fb69799bfe9a0d566d22c41a919 100644 (file)
@@ -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);
 }