[cfe-commits] r45921 - /cfe/trunk/include/clang/Analysis/PathSensitive/ExplodedNode.h

Ted Kremenek kremenek at apple.com
Sat Jan 12 19:55:50 PST 2008


Author: kremenek
Date: Sat Jan 12 21:55:50 2008
New Revision: 45921

URL: http://llvm.org/viewvc/llvm-project?rev=45921&view=rev
Log:
Changed implementation of successor and predecessor sets for ExplodedNode
to optimize for the common case of having a single predecessor and a single
successor.

Modified:
    cfe/trunk/include/clang/Analysis/PathSensitive/ExplodedNode.h

Modified: cfe/trunk/include/clang/Analysis/PathSensitive/ExplodedNode.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/ExplodedNode.h?rev=45921&r1=45920&r2=45921&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/ExplodedNode.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/ExplodedNode.h Sat Jan 12 21:55:50 2008
@@ -16,32 +16,97 @@
 #ifndef LLVM_CLANG_ANALYSIS_EXPLODEDNODE
 #define LLVM_CLANG_ANALYSIS_EXPLODEDNODE
 
-#include "clang/Analysis/ProgramEdge.h"
-#include "llvm/ADT/SmallVector.h"
+#include "clang/Analysis/ProgramPoint.h"
 #include "llvm/ADT/FoldingSet.h"
 #include "llvm/ADT/GraphTraits.h"
 #include "llvm/ADT/DepthFirstIterator.h"
+#include <vector>
 
 namespace clang {
-  
-class GREngineImpl;
 
+class ExplodedGraphImpl;
+class ExplodedNodeImpl;
+
+/// ExplodeNodeGroup - A utility class used to represent the set of successor
+///  and predecessor nodes of a node.  Most nodes will have only 1 successor
+///  and 1 predecessor, so class allows us to store such unit sets of nodes
+///  using a single pointer without allocating an entire vector.  For
+///  larger sets of nodes, we dynamically allocate a vector.  This class
+///  will likely be revised in the future to further improve performance and
+///  to reduce memory footprint.
+class ExplodedNodeGroup {
+  enum { Size1 = 0x0, SizeOther = 0x1, Flags = 0x1 };
+  uintptr_t P;
+
+  unsigned getKind() const { return P & Flags; }
+
+  std::vector<ExplodeNodeImpl*>& getVector() {
+    assert (getKind() == SizeOther);
+    return *reinterpret_cast<std::vector<ExplodeNodeImpl*>*>(P & ~Flags);
+  }
+
+  ExplodeNodeImpl* getNode() {
+    assert (getKind() == Size1);
+    return reinterpret_cast<ExplodeNodeImpl*>(P);
+  }
+
+public:
+  ExplodedNodeGroup() : P(0) {}
+
+  ~ExplodedNodeGroup() { if (getKind() == SizeOther) delete &getVector(); }
+
+  inline ExplodedNodeImpl** begin() const {
+    if (getKind() == Size1)
+      return (ExplodedNodeImpl**) &P;
+    else
+      return getVector().begin();
+  }
+  
+  inline ExplodedNodeImpl** end() const {
+    if (getKind() == Size1)
+      return ((ExplodedNodeImpl**) &P)+1;
+    else
+      return getVector().end();
+  }
+    
+  inline unsigned size() const {
+    if (getKind() == Size1)
+      return getNode() ? 1 : 0;
+    else
+      return getVector().size();
+  }
+  
+  inline bool empty() const {
+    if (getKind() == Size1)
+      return getNode() ? false : true;
+    else
+      return getVector().empty();
+  }
+  
+  inline void addNode(ExplodedNodeImpl* N) {
+    if (getKind() == Size1) {
+      if (ExplodedNodeImpl* NOld = getNode()) {
+        std::vector<ExplodeNodeImpl*>* V = new std::vector<ExplodeNodeImpl*>();
+        V->push_back(NOld);
+        V->push_back(N);
+        P = reinterpret_cast<uintptr_t>(V) & SizeOther;
+      }
+      else
+        P = reinterpret_cast<uintptr_t>(N);
+    }
+    else
+      getVector().push_back(N);
+  }
+};
+
+/// ExplodeNodeImpl - 
 class ExplodedNodeImpl : public llvm::FoldingSetNode {
 protected:
-  friend class GREngineImpl;
-  
-  /// nodeID - A unique ID for the node.  This number indicates the
-  ///  creation order of vertices, with lower numbers being created first.
-  ///  The first created node has nodeID == 0.
-  const unsigned nodeID:30;
-  
-  /// IsInfeasible - Indicates whether the node represents an infeasible
-  ///  program state.
-  unsigned IsInfeasible:1;
-  
+  friend class ExplodedGraphImpl;
+    
   /// Location - The program location (within a function body) associated
-  ///  with this node.  The location is a 'ProgramEdge' in the CFG.
-  const ProgramEdge Location;
+  ///  with this node.
+  const ProgramPoint Location;
   
   /// State - The state associated with this node. Normally this value
   ///  is immutable, but we anticipate there will be times when algorithms
@@ -49,48 +114,31 @@
   void* State;
 
   /// Preds - The predecessors of this node.
-  llvm::SmallVector<ExplodedNodeImpl*,2> Preds;
+  ExplodedNodeGroup Preds;
   
   /// Succs - The successors of this node.
-  llvm::SmallVector<ExplodedNodeImpl*,2> Succs;
-    
-  // FIXME: Preds and Succs only grow, not shrink.  It would be nice
-  //  if these were allocated from the same BumpPtrAllocator as
-  //  the nodes themselves.
+  ExplodedNodeGroup Succs;
 
-  /// Construct a ExplodedNodeImpl with the given node ID, program edge,
-  ///  and state.
-  explicit ExplodedNodeImpl(unsigned ID, const ProgramEdge& loc, void* state)
-    : nodeID(ID), IsInfeasible(0), Location(loc), State(state) {}
+  /// Construct a ExplodedNodeImpl with the provided location and state.
+  explicit ExplodedNodeImpl(const ProgramLocation& loc, void* state)
+    : Location(loc), State(state) {}
 
-  /// addUntypedPredeccessor - Adds a predecessor to the current node, and 
+  /// addPredeccessor - Adds a predecessor to the current node, and 
   ///  in tandem add this node as a successor of the other node.  This
-  ///  "untyped" version is intended to be used only by GREngineImpl;
-  ///  normal clients should use 'addPredecessor' in ExplodedNode<>.
-  void addUntypedPredecessor(ExplodedNodeImpl* V) {
-    assert (!V->isInfeasible() &&
-            "Cannot add successors to an infeasible node.");
-    
-    Preds.push_back(V);
-    V->Succs.push_back(V);
+  ///  method is intended to be used only by ExplodedGraphImpl.
+  void addPredecessor(ExplodedNodeImpl* V) {
+    Preds.addNode(V);
+    V->Succs.addNode(this);
   }
 
 public:
   /// getLocation - Returns the edge associated with the given node.
-  const ProgramEdge& getLocation() const { return Location; }
-  
-  /// getNodeID - Returns the unique ID of the node.  These IDs reflect
-  ///  the order in which vertices were generated by GREngineImpl.
-  unsigned getNodeID() const { return nodeID; }
-  
-  /// isInfeasible - Returns true if the node represents an infeasible
-  ///  program state.
-  bool isInfeasible() const { return IsInfeasible ? true : false; }
-  
-  /// markInfeasible - The node is marked as being an infeasible program
-  ///  state.
-  void markInfeasible() { Infeasible = 1; }
-  
+  const ProgramPoint& getLocation() const { return Location; }
+
+  unsigned succ_size() const { return Succs.size(); }
+  unsigned pred_size() const { return Preds.size(); }
+  bool succ_empty() const { return Succs.empty(); }
+  bool pred_empty() const { return Preds.size(); }
 };
 
   
@@ -111,8 +159,8 @@
   /// Construct a ExplodedNodeImpl with the given node ID, program edge,
   ///  and state.
   explicit ExplodedNode(unsigned ID, const ProgramEdge& loc, StateTy state)
-  : ExplodedNodeImpl(ID,loc,GRTrait<StateTy>::toPtr(state)) {}
-  
+  : ExplodedNodeImpl(ID, loc, GRTrait<StateTy>::toPtr(state)) {}
+
   /// getState - Returns the state associated with the node.  
   inline StateTy getState() const {
     return GRTrait<StateTy>::toState(State);
@@ -120,55 +168,37 @@
   
   // Profiling (for FoldingSet).
   inline void Profile(llvm::FoldingSetNodeID& ID) const {
-    StateTy::Profile(ID,getState());
+    StateTy::Profile(ID, getState());
   }
 
   // Iterators over successor and predecessor vertices.
-  typedef ExplodedNode*        succ_iterator;
-  typedef const ExplodedNode*  const_succ_iterator;
-  typedef ExplodedNode*        pred_iterator;
-  typedef const ExplodedNode*  const_pred_iterator;
-  
-  pred_iterator pred_begin() {
-    return static_cast<pred_iterator>(Preds.begin());
-  }
-  
-  pred_iterator pred_end() {
-    return static_cast<pred_iterator>(Preds.end());
-  }
-  
+  typedef ExplodedNode**       succ_iterator;
+  typedef const ExplodedNode** const_succ_iterator;
+  typedef ExplodedNode**       pred_iterator;
+  typedef const ExplodedNode** const_pred_pred_iterator;
+                     
+  pred_iterator pred_begin() { return (ExplodedNode**) Pred.begin(); }  
+  pred_iterator pred_end() { return (ExplodedNode**) Pred.end(); }
+
   const_pred_iterator pred_begin() const {
-    return static_cast<const_pred_iterator>(Preds.begin());
-  }
-  
+    return const_cast<ExplodedNode*>(this)->pred_begin();
+  }  
   const_pred_iterator pred_end() const {
-    return static_cast<const_pred_iterator>(Preds.end());
-  }
-  
-  succ_iterator succ_begin() {
-    return static_cast<succ_iterator>(Succs.begin());
+    return const_cast<ExplodedNode*>(this)->pred_end();
   }
   
-  succ_iterator succ_end() {
-    return static_cast<succ_iterator>(Succs.end());
-  }
+  succ_iterator succ_begin() { return (ExplodedNode**) Succ.begin(); }
+  succ_iterator succ_end() { return (ExplodedNode**) Succ.end(); }
   
   const_succ_iterator succ_begin() const {
-    return static_cast<const_succ_iterator>(Succs.begin());
-  }
-  
+    return const_cast<ExplodedNode*>(this)->succ_begin();
+  }  
   const_succ_iterator succ_end() const {
-    return static_cast<const_succ_iterator>(Succs.end());
-  }
-  
-  unsigned succ_size() const { return Succs.size(); }
-  bool succ_empty() const { return Succs.empty(); }
-  
-  unsigned pred_size() const { return Preds.size(); }
-  unsigned pred_empty() const { return Preds.empty(); }
+    return const_cast<ExplodedNode*>(this)->succ_end();
+  }  
 };
   
-} // end namespace clang
+} // end clang namespace
 
 // GraphTraits for ExplodedNodes.
 
@@ -226,5 +256,6 @@
     return df_end(N);
   }
 };
-}
+                     
+} // end llvm namespace
 #endif





More information about the cfe-commits mailing list