[cfe-commits] r149336 - in /cfe/trunk: 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

Argyrios Kyrtzidis akyrtzi at gmail.com
Mon Jan 30 18:14:25 PST 2012


Author: akirtzidis
Date: Mon Jan 30 20:14:24 2012
New Revision: 149336

URL: http://llvm.org/viewvc/llvm-project?rev=149336&view=rev
Log:
Revert r149311 which failed to compile.

Original log:

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.

Modified:
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h
    cfe/trunk/lib/StaticAnalyzer/Core/Checker.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h?rev=149336&r1=149335&r2=149336&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h Mon Jan 30 20:14:24 2012
@@ -119,11 +119,14 @@
   explicit ExplodedNode(const ProgramPoint &loc, ProgramStateRef state,
                         bool IsSink)
     : Location(loc), State(state) {
+    const_cast<ProgramState*>(State)->incrementReferenceCount();
     if (IsSink)
       Succs.setFlag();
   }
   
-  ~ExplodedNode() {}
+  ~ExplodedNode() {
+    const_cast<ProgramState*>(State)->decrementReferenceCount();
+  }
 
   /// getLocation - Returns the edge associated with the given node.
   ProgramPoint getLocation() const { return Location; }
@@ -153,7 +156,7 @@
                       ProgramStateRef state,
                       bool IsSink) {
     ID.Add(Loc);
-    ID.AddPointer(state.getPtr());
+    ID.AddPointer(state);
     ID.AddBoolean(IsSink);
   }
 

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h?rev=149336&r1=149335&r2=149336&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h Mon Jan 30 20:14:24 2012
@@ -93,6 +93,7 @@
   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);
@@ -106,6 +107,9 @@
   /// 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; }
@@ -123,7 +127,7 @@
   /// 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, const ProgramState *V) {
+  static void Profile(llvm::FoldingSetNodeID& ID, ProgramStateRef V) {
     V->Env.Profile(ID);
     ID.AddPointer(V->store);
     V->GDM.Profile(ID);
@@ -372,8 +376,14 @@
   void dumpTaint() const;
 
 private:
-  friend void ProgramStateRetain(const ProgramState *state);
-  friend void ProgramStateRelease(const ProgramState *state);
+  /// 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;
+  }
   
   ProgramStateRef 
   invalidateRegionsImpl(ArrayRef<const MemRegion *> Regions,
@@ -382,13 +392,45 @@
                         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. */
@@ -411,6 +453,10 @@
 
   /// 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;
@@ -517,6 +563,10 @@
     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.
   //==---------------------------------------------------------------------==//

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h?rev=149336&r1=149335&r2=149336&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h Mon Jan 30 20:14:24 2012
@@ -10,31 +10,11 @@
 #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;
-  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;
+  typedef const ProgramState* ProgramStateRef;
 }
 }
 

Modified: cfe/trunk/lib/StaticAnalyzer/Core/Checker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/Checker.cpp?rev=149336&r1=149335&r2=149336&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/Checker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/Checker.cpp Mon Jan 30 20:14:24 2012
@@ -11,7 +11,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
 #include "clang/StaticAnalyzer/Core/Checker.h"
 
 using namespace clang;

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=149336&r1=149335&r2=149336&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Mon Jan 30 20:14:24 2012
@@ -238,8 +238,13 @@
 
 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(),
@@ -1851,7 +1856,7 @@
     }
 
     ProgramStateRef state = N->getState();
-    Out << "\\|StateID: " << (void*) state.getPtr()
+    Out << "\\|StateID: " << (void*) state
         << " NodeID: " << (void*) N << "\\|";
     state->printDOT(Out);
 

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp?rev=149336&r1=149335&r2=149336&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp Mon Jan 30 20:14:24 2012
@@ -25,26 +25,6 @@
 // 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),
@@ -348,10 +328,23 @@
   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);
 }
@@ -375,11 +368,12 @@
   }
   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);
 }





More information about the cfe-commits mailing list