From: Ted Kremenek Date: Sun, 13 Jan 2008 03:55:50 +0000 (+0000) Subject: Changed implementation of successor and predecessor sets for ExplodedNode X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=46dc4e5f526407a089a4fb3fdf12e20d04f08c86;p=clang Changed implementation of successor and predecessor sets for ExplodedNode to optimize for the common case of having a single predecessor and a single successor. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@45921 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Analysis/PathSensitive/ExplodedNode.h b/include/clang/Analysis/PathSensitive/ExplodedNode.h index 48ba0e29bb..72e167e227 100644 --- a/include/clang/Analysis/PathSensitive/ExplodedNode.h +++ b/include/clang/Analysis/PathSensitive/ExplodedNode.h @@ -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 namespace clang { - -class GREngineImpl; -class ExplodedNodeImpl : public llvm::FoldingSetNode { -protected: - friend 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& getVector() { + assert (getKind() == SizeOther); + return *reinterpret_cast*>(P & ~Flags); + } + + ExplodeNodeImpl* getNode() { + assert (getKind() == Size1); + return reinterpret_cast(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(); + } - /// 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; + 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(); + } - /// IsInfeasible - Indicates whether the node represents an infeasible - /// program state. - unsigned IsInfeasible:1; + 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* V = new std::vector(); + V->push_back(NOld); + V->push_back(N); + P = reinterpret_cast(V) & SizeOther; + } + else + P = reinterpret_cast(N); + } + else + getVector().push_back(N); + } +}; + +/// ExplodeNodeImpl - +class ExplodedNodeImpl : public llvm::FoldingSetNode { +protected: + 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 @@ protected: void* State; /// Preds - The predecessors of this node. - llvm::SmallVector Preds; + ExplodedNodeGroup Preds; /// Succs - The successors of this node. - llvm::SmallVector 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 @@ public: /// 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::toPtr(state)) {} - + : ExplodedNodeImpl(ID, loc, GRTrait::toPtr(state)) {} + /// getState - Returns the state associated with the node. inline StateTy getState() const { return GRTrait::toState(State); @@ -120,55 +168,37 @@ public: // 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(Preds.begin()); - } - - pred_iterator pred_end() { - return static_cast(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(Preds.begin()); - } - + return const_cast(this)->pred_begin(); + } const_pred_iterator pred_end() const { - return static_cast(Preds.end()); - } - - succ_iterator succ_begin() { - return static_cast(Succs.begin()); + return const_cast(this)->pred_end(); } - succ_iterator succ_end() { - return static_cast(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(Succs.begin()); - } - + return const_cast(this)->succ_begin(); + } const_succ_iterator succ_end() const { - return static_cast(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(this)->succ_end(); + } }; -} // end namespace clang +} // end clang namespace // GraphTraits for ExplodedNodes. @@ -226,5 +256,6 @@ struct GraphTraits*> { return df_end(N); } }; -} + +} // end llvm namespace #endif