[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