<commit_before>//===- ShadowNodeEliminate.cpp - Optimize away shadow nodes ---------------===//
//
// This file contains two shadow node optimizations:
//   1. UnlinkUndistinguishableShadowNodes - Often, after unification, shadow
//      nodes are left around that should not exist anymore.  An example is when
//      a shadow gets unified with a 'new' node, the following graph gets
//      generated:  %X -> Shadow, %X -> New.  Since all of the edges to the
//      shadow node also all go to the New node, we can eliminate the shadow.
//
//   2. RemoveUnreachableShadowNodes - Remove shadow nodes that are not
//      reachable from some other node in the graph.  Unreachable shadow nodes
//      are left lying around because other transforms don't go to the trouble
//      or removing them, since this pass exists.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/DataStructure.h"
#include "llvm/Value.h"
#include "Support/STLExtras.h"
#include <algorithm>

//#define DEBUG_NODE_ELIMINATE 1

bool AllocDSNode::isEquivalentTo(DSNode *Node) const {
  if (AllocDSNode *N = dyn_cast<AllocDSNode>(Node))
    return N->Allocation == Allocation;
  return false;
}

bool GlobalDSNode::isEquivalentTo(DSNode *Node) const {
  if (GlobalDSNode *G = dyn_cast<GlobalDSNode>(Node))
    return G->Val == Val;
  return false;
}

bool CallDSNode::isEquivalentTo(DSNode *Node) const {
  if (CallDSNode *C = dyn_cast<CallDSNode>(Node))
    return C->CI == CI && C->ArgLinks == ArgLinks;
  return false;
}

bool ArgDSNode::isEquivalentTo(DSNode *Node) const {
  return false;
}

// NodesAreEquivalent - Check to see if the nodes are equivalent in all ways
// except node type.  Since we know N1 is a shadow node, N2 is allowed to be
// any type.
//
bool ShadowDSNode::isEquivalentTo(DSNode *Node) const {
  return !isCriticalNode();              // Must not be a critical node...
}

// isIndistinguishableNode - A node is indistinguishable if some other node
// has exactly the same incoming links to it and if the node considers itself
// to be the same as the other node...
//
bool isIndistinguishableNode(DSNode *DN) {
  if (DN->getReferrers().empty()) {       // No referrers...
    if (isa<ShadowDSNode>(DN) || isa<AllocDSNode>(DN))
      return true;  // Node is trivially dead
    else
      return false;
  }

  // Pick a random referrer... Ptr is the things that the referrer points to.
  // Since DN is in the Ptr set, look through the set seeing if there are any
  // other nodes that are exactly equilivant to DN (with the exception of node
  // type), but are not DN.  If anything exists, then DN is indistinguishable.
  //
  const std::vector<PointerValSet*> &Refs = DN->getReferrers();
  for (unsigned R = 0, RE = Refs.size(); R != RE; ++R) {
    const PointerValSet &Ptr = *Refs[R];

    for (unsigned i = 0, e = Ptr.size(); i != e; ++i) {
      DSNode *N2 = Ptr[i].Node;
      if (Ptr[i].Index == 0 && N2 != cast<DSNode>(DN) &&
          DN->getType() == N2->getType() && DN->isEquivalentTo(N2)) {

        // Otherwise, the nodes can be merged.  Make sure that N2 contains all
        // of the  outgoing edges (fields) that DN does...
        //
        assert(DN->getNumLinks() == N2->getNumLinks() &&
               "Same type, diff # fields?");
        for (unsigned i = 0, e = DN->getNumLinks(); i != e; ++i)
          N2->getLink(i).add(DN->getLink(i));

        // Now make sure that all of the nodes that point to the shadow node
        // also  point to the node that we are merging it with...
        //
        const std::vector<PointerValSet*> &Refs = DN->getReferrers();
        for (unsigned i = 0, e = Refs.size(); i != e; ++i) {
          PointerValSet &PVS = *Refs[i];
          // FIXME: this is incorrect if the referring pointer has index != 0
          //
          PVS.add(N2);
        }
        return true;
      }
    }
  }

  // Otherwise, nothing found, perhaps next time....
  return false;
}

template<typename NodeTy>
bool removeIndistinguishableNode(std::vector<NodeTy*> &Nodes) {
  bool Changed = false;
  std::vector<NodeTy*>::iterator I = Nodes.begin();
  while (I != Nodes.end()) {
    if (isIndistinguishableNode(*I)) {
#ifdef DEBUG_NODE_ELIMINATE
      cerr << "Found Indistinguishable Node:\n";
      (*I)->print(cerr);
#endif
      (*I)->removeAllIncomingEdges();
      delete *I;
      I = Nodes.erase(I);
      Changed = true;
    } else {
      ++I;
    }
  }
  return Changed;
}

// UnlinkUndistinguishableShadowNodes - Eliminate shadow nodes that are not
// distinguishable from some other node in the graph...
//
bool FunctionDSGraph::UnlinkUndistinguishableShadowNodes() {
  // Loop over all of the shadow nodes, checking to see if they are
  // indistinguishable from some other node.  If so, eliminate the node!
  //
  return
    removeIndistinguishableNode(AllocNodes) |
    removeIndistinguishableNode(ShadowNodes) |
    removeIndistinguishableNode(GlobalNodes);
}

static void MarkReferredNodesReachable(DSNode *N,
                                       vector<ShadowDSNode*> &ShadowNodes,
                                       vector<bool> &ReachableShadowNodes,
                                       vector<AllocDSNode*>  &AllocNodes,
                                       vector<bool> &ReachableAllocNodes);

static inline void MarkReferredNodeSetReachable(const PointerValSet &PVS,
                                            vector<ShadowDSNode*> &ShadowNodes,
                                            vector<bool> &ReachableShadowNodes,
                                            vector<AllocDSNode*>  &AllocNodes,
                                            vector<bool> &ReachableAllocNodes) {
  for (unsigned i = 0, e = PVS.size(); i != e; ++i)
    if (isa<ShadowDSNode>(PVS[i].Node) || isa<ShadowDSNode>(PVS[i].Node))
      MarkReferredNodesReachable(PVS[i].Node, ShadowNodes, ReachableShadowNodes,
                                 AllocNodes, ReachableAllocNodes);
}

static void MarkReferredNodesReachable(DSNode *N,
                                       vector<ShadowDSNode*> &ShadowNodes,
                                       vector<bool> &ReachableShadowNodes,
                                       vector<AllocDSNode*>  &AllocNodes,
                                       vector<bool> &ReachableAllocNodes) {
  assert(ShadowNodes.size() == ReachableShadowNodes.size());
  assert(AllocNodes.size()  == ReachableAllocNodes.size());

  if (ShadowDSNode *Shad = dyn_cast<ShadowDSNode>(N)) {
    vector<ShadowDSNode*>::iterator I =
      std::find(ShadowNodes.begin(), ShadowNodes.end(), Shad);
    unsigned i = I-ShadowNodes.begin();
    if (ReachableShadowNodes[i]) return;  // Recursion detected, abort...
    ReachableShadowNodes[i] = true;
  } else if (AllocDSNode *Alloc = dyn_cast<AllocDSNode>(N)) {
    vector<AllocDSNode*>::iterator I =
      std::find(AllocNodes.begin(), AllocNodes.end(), Alloc);
    unsigned i = I-AllocNodes.begin();
    if (ReachableAllocNodes[i]) return;  // Recursion detected, abort...
    ReachableAllocNodes[i] = true;
  }

  for (unsigned i = 0, e = N->getNumLinks(); i != e; ++i)
    MarkReferredNodeSetReachable(N->getLink(i),
                                 ShadowNodes, ReachableShadowNodes,
                                 AllocNodes, ReachableAllocNodes);

  const std::vector<PointerValSet> *Links = N->getAuxLinks();
  if (Links)
    for (unsigned i = 0, e = Links->size(); i != e; ++i)
      MarkReferredNodeSetReachable((*Links)[i],
                                   ShadowNodes, ReachableShadowNodes,
                                   AllocNodes, ReachableAllocNodes);
}

bool FunctionDSGraph::RemoveUnreachableShadowNodes() {
  bool Changed = false;
  while (1) {
    // Reachable*Nodes - Contains true if there is an edge from a reachable
    // node to the numbered node...
    //
    vector<bool> ReachableShadowNodes(ShadowNodes.size());
    vector<bool> ReachableAllocNodes (AllocNodes.size());

    // Mark all shadow nodes that have edges from other nodes as reachable.
    // Recursively mark any shadow nodes pointed to by the newly live shadow
    // nodes as also alive.
    //
    for (unsigned i = 0, e = ArgNodes.size(); i != e; ++i)
      MarkReferredNodesReachable(ArgNodes[i],
                                 ShadowNodes, ReachableShadowNodes,
                                 AllocNodes, ReachableAllocNodes);

    for (unsigned i = 0, e = GlobalNodes.size(); i != e; ++i)
      MarkReferredNodesReachable(GlobalNodes[i],
                                 ShadowNodes, ReachableShadowNodes,
                                 AllocNodes, ReachableAllocNodes);

    for (unsigned i = 0, e = CallNodes.size(); i != e; ++i)
      MarkReferredNodesReachable(CallNodes[i],
                                 ShadowNodes, ReachableShadowNodes,
                                 AllocNodes, ReachableAllocNodes);

    // Mark all nodes in the return set as being reachable...
    MarkReferredNodeSetReachable(RetNode,
                                 ShadowNodes, ReachableShadowNodes,
                                 AllocNodes, ReachableAllocNodes);

    // Mark all nodes in the value map as being reachable...
    for (std::map<Value*, PointerValSet>::iterator I = ValueMap.begin(),
           E = ValueMap.end(); I != E; ++I)
      MarkReferredNodeSetReachable(I->second,
                                   ShadowNodes, ReachableShadowNodes,
                                   AllocNodes, ReachableAllocNodes);

    // At this point, all reachable shadow nodes have a true value in the
    // Reachable vector.  This means that any shadow nodes without an entry in
    // the reachable vector are not reachable and should be removed.  This is
    // a two part process, because we must drop all references before we delete
    // the shadow nodes [in case cycles exist].
    //
    bool LocalChange = false;
    for (unsigned i = 0; i != ShadowNodes.size(); ++i)
      if (!ReachableShadowNodes[i]) {
        // Track all unreachable nodes...
#if DEBUG_NODE_ELIMINATE
        cerr << "Unreachable node eliminated:\n";
        ShadowNodes[i]->print(cerr);
#endif
        ShadowNodes[i]->removeAllIncomingEdges();
        delete ShadowNodes[i];

        // Remove from reachable...
        ReachableShadowNodes.erase(ReachableShadowNodes.begin()+i);
        ShadowNodes.erase(ShadowNodes.begin()+i);   // Remove node entry
        --i;  // Don't skip the next node.
        LocalChange = true;
      }

    for (unsigned i = 0; i != AllocNodes.size(); ++i)
      if (!ReachableAllocNodes[i]) {
        // Track all unreachable nodes...
#if DEBUG_NODE_ELIMINATE
        cerr << "Unreachable node eliminated:\n";
        AllocNodes[i]->print(cerr);
#endif
        AllocNodes[i]->removeAllIncomingEdges();
        delete AllocNodes[i];

        // Remove from reachable...
        ReachableAllocNodes.erase(ReachableAllocNodes.begin()+i);
        AllocNodes.erase(AllocNodes.begin()+i);   // Remove node entry
        --i;  // Don't skip the next node.
        LocalChange = true;
      }

    if (!LocalChange) return Changed;      // No more dead nodes...

    Changed = true;
  }
}
<commit_msg>Ooops, I did such a great job pruning nodes, that I accidentally deleted ALL allocation nodes... hrm... bad.<commit_after>//===- ShadowNodeEliminate.cpp - Optimize away shadow nodes ---------------===//
//
// This file contains two shadow node optimizations:
//   1. UnlinkUndistinguishableShadowNodes - Often, after unification, shadow
//      nodes are left around that should not exist anymore.  An example is when
//      a shadow gets unified with a 'new' node, the following graph gets
//      generated:  %X -> Shadow, %X -> New.  Since all of the edges to the
//      shadow node also all go to the New node, we can eliminate the shadow.
//
//   2. RemoveUnreachableShadowNodes - Remove shadow nodes that are not
//      reachable from some other node in the graph.  Unreachable shadow nodes
//      are left lying around because other transforms don't go to the trouble
//      or removing them, since this pass exists.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/DataStructure.h"
#include "llvm/Value.h"
#include "Support/STLExtras.h"
#include <algorithm>

//#define DEBUG_NODE_ELIMINATE 1

bool AllocDSNode::isEquivalentTo(DSNode *Node) const {
  if (AllocDSNode *N = dyn_cast<AllocDSNode>(Node))
    return N->Allocation == Allocation;
  return false;
}

bool GlobalDSNode::isEquivalentTo(DSNode *Node) const {
  if (GlobalDSNode *G = dyn_cast<GlobalDSNode>(Node))
    return G->Val == Val;
  return false;
}

bool CallDSNode::isEquivalentTo(DSNode *Node) const {
  if (CallDSNode *C = dyn_cast<CallDSNode>(Node))
    return C->CI == CI && C->ArgLinks == ArgLinks;
  return false;
}

bool ArgDSNode::isEquivalentTo(DSNode *Node) const {
  return false;
}

// NodesAreEquivalent - Check to see if the nodes are equivalent in all ways
// except node type.  Since we know N1 is a shadow node, N2 is allowed to be
// any type.
//
bool ShadowDSNode::isEquivalentTo(DSNode *Node) const {
  return !isCriticalNode();              // Must not be a critical node...
}

// isIndistinguishableNode - A node is indistinguishable if some other node
// has exactly the same incoming links to it and if the node considers itself
// to be the same as the other node...
//
bool isIndistinguishableNode(DSNode *DN) {
  if (DN->getReferrers().empty()) {       // No referrers...
    if (isa<ShadowDSNode>(DN) || isa<AllocDSNode>(DN))
      return true;  // Node is trivially dead
    else
      return false;
  }

  // Pick a random referrer... Ptr is the things that the referrer points to.
  // Since DN is in the Ptr set, look through the set seeing if there are any
  // other nodes that are exactly equilivant to DN (with the exception of node
  // type), but are not DN.  If anything exists, then DN is indistinguishable.
  //
  const std::vector<PointerValSet*> &Refs = DN->getReferrers();
  for (unsigned R = 0, RE = Refs.size(); R != RE; ++R) {
    const PointerValSet &Ptr = *Refs[R];

    for (unsigned i = 0, e = Ptr.size(); i != e; ++i) {
      DSNode *N2 = Ptr[i].Node;
      if (Ptr[i].Index == 0 && N2 != cast<DSNode>(DN) &&
          DN->getType() == N2->getType() && DN->isEquivalentTo(N2)) {

        // Otherwise, the nodes can be merged.  Make sure that N2 contains all
        // of the  outgoing edges (fields) that DN does...
        //
        assert(DN->getNumLinks() == N2->getNumLinks() &&
               "Same type, diff # fields?");
        for (unsigned i = 0, e = DN->getNumLinks(); i != e; ++i)
          N2->getLink(i).add(DN->getLink(i));

        // Now make sure that all of the nodes that point to the shadow node
        // also  point to the node that we are merging it with...
        //
        const std::vector<PointerValSet*> &Refs = DN->getReferrers();
        for (unsigned i = 0, e = Refs.size(); i != e; ++i) {
          PointerValSet &PVS = *Refs[i];
          // FIXME: this is incorrect if the referring pointer has index != 0
          //
          PVS.add(N2);
        }
        return true;
      }
    }
  }

  // Otherwise, nothing found, perhaps next time....
  return false;
}

template<typename NodeTy>
bool removeIndistinguishableNode(std::vector<NodeTy*> &Nodes) {
  bool Changed = false;
  std::vector<NodeTy*>::iterator I = Nodes.begin();
  while (I != Nodes.end()) {
    if (isIndistinguishableNode(*I)) {
#ifdef DEBUG_NODE_ELIMINATE
      cerr << "Found Indistinguishable Node:\n";
      (*I)->print(cerr);
#endif
      (*I)->removeAllIncomingEdges();
      delete *I;
      I = Nodes.erase(I);
      Changed = true;
    } else {
      ++I;
    }
  }
  return Changed;
}

// UnlinkUndistinguishableShadowNodes - Eliminate shadow nodes that are not
// distinguishable from some other node in the graph...
//
bool FunctionDSGraph::UnlinkUndistinguishableShadowNodes() {
  // Loop over all of the shadow nodes, checking to see if they are
  // indistinguishable from some other node.  If so, eliminate the node!
  //
  return
    removeIndistinguishableNode(AllocNodes) |
    removeIndistinguishableNode(ShadowNodes) |
    removeIndistinguishableNode(GlobalNodes);
}

static void MarkReferredNodesReachable(DSNode *N,
                                       vector<ShadowDSNode*> &ShadowNodes,
                                       vector<bool> &ReachableShadowNodes,
                                       vector<AllocDSNode*>  &AllocNodes,
                                       vector<bool> &ReachableAllocNodes);

static inline void MarkReferredNodeSetReachable(const PointerValSet &PVS,
                                            vector<ShadowDSNode*> &ShadowNodes,
                                            vector<bool> &ReachableShadowNodes,
                                            vector<AllocDSNode*>  &AllocNodes,
                                            vector<bool> &ReachableAllocNodes) {
  for (unsigned i = 0, e = PVS.size(); i != e; ++i)
    if (isa<ShadowDSNode>(PVS[i].Node) || isa<AllocDSNode>(PVS[i].Node))
      MarkReferredNodesReachable(PVS[i].Node, ShadowNodes, ReachableShadowNodes,
                                 AllocNodes, ReachableAllocNodes);
}

static void MarkReferredNodesReachable(DSNode *N,
                                       vector<ShadowDSNode*> &ShadowNodes,
                                       vector<bool> &ReachableShadowNodes,
                                       vector<AllocDSNode*>  &AllocNodes,
                                       vector<bool> &ReachableAllocNodes) {
  assert(ShadowNodes.size() == ReachableShadowNodes.size());
  assert(AllocNodes.size()  == ReachableAllocNodes.size());

  if (ShadowDSNode *Shad = dyn_cast<ShadowDSNode>(N)) {
    vector<ShadowDSNode*>::iterator I =
      std::find(ShadowNodes.begin(), ShadowNodes.end(), Shad);
    unsigned i = I-ShadowNodes.begin();
    if (ReachableShadowNodes[i]) return;  // Recursion detected, abort...
    ReachableShadowNodes[i] = true;
  } else if (AllocDSNode *Alloc = dyn_cast<AllocDSNode>(N)) {
    vector<AllocDSNode*>::iterator I =
      std::find(AllocNodes.begin(), AllocNodes.end(), Alloc);
    unsigned i = I-AllocNodes.begin();
    if (ReachableAllocNodes[i]) return;  // Recursion detected, abort...
    ReachableAllocNodes[i] = true;
  }

  for (unsigned i = 0, e = N->getNumLinks(); i != e; ++i)
    MarkReferredNodeSetReachable(N->getLink(i),
                                 ShadowNodes, ReachableShadowNodes,
                                 AllocNodes, ReachableAllocNodes);

  const std::vector<PointerValSet> *Links = N->getAuxLinks();
  if (Links)
    for (unsigned i = 0, e = Links->size(); i != e; ++i)
      MarkReferredNodeSetReachable((*Links)[i],
                                   ShadowNodes, ReachableShadowNodes,
                                   AllocNodes, ReachableAllocNodes);
}

bool FunctionDSGraph::RemoveUnreachableShadowNodes() {
  bool Changed = false;

  while (1) {
    // Reachable*Nodes - Contains true if there is an edge from a reachable
    // node to the numbered node...
    //
    vector<bool> ReachableShadowNodes(ShadowNodes.size());
    vector<bool> ReachableAllocNodes (AllocNodes.size());

    // Mark all shadow nodes that have edges from other nodes as reachable.
    // Recursively mark any shadow nodes pointed to by the newly live shadow
    // nodes as also alive.
    //
    for (unsigned i = 0, e = ArgNodes.size(); i != e; ++i)
      MarkReferredNodesReachable(ArgNodes[i],
                                 ShadowNodes, ReachableShadowNodes,
                                 AllocNodes, ReachableAllocNodes);

    for (unsigned i = 0, e = GlobalNodes.size(); i != e; ++i)
      MarkReferredNodesReachable(GlobalNodes[i],
                                 ShadowNodes, ReachableShadowNodes,
                                 AllocNodes, ReachableAllocNodes);

    for (unsigned i = 0, e = CallNodes.size(); i != e; ++i)
      MarkReferredNodesReachable(CallNodes[i],
                                 ShadowNodes, ReachableShadowNodes,
                                 AllocNodes, ReachableAllocNodes);

    // Mark all nodes in the return set as being reachable...
    MarkReferredNodeSetReachable(RetNode,
                                 ShadowNodes, ReachableShadowNodes,
                                 AllocNodes, ReachableAllocNodes);

    // Mark all nodes in the value map as being reachable...
    for (std::map<Value*, PointerValSet>::iterator I = ValueMap.begin(),
           E = ValueMap.end(); I != E; ++I)
      MarkReferredNodeSetReachable(I->second,
                                   ShadowNodes, ReachableShadowNodes,
                                   AllocNodes, ReachableAllocNodes);

    // At this point, all reachable shadow nodes have a true value in the
    // Reachable vector.  This means that any shadow nodes without an entry in
    // the reachable vector are not reachable and should be removed.  This is
    // a two part process, because we must drop all references before we delete
    // the shadow nodes [in case cycles exist].
    //
    bool LocalChange = false;
    for (unsigned i = 0; i != ShadowNodes.size(); ++i)
      if (!ReachableShadowNodes[i]) {
        // Track all unreachable nodes...
#if DEBUG_NODE_ELIMINATE
        cerr << "Unreachable node eliminated:\n";
        ShadowNodes[i]->print(cerr);
#endif
        ShadowNodes[i]->removeAllIncomingEdges();
        delete ShadowNodes[i];

        // Remove from reachable...
        ReachableShadowNodes.erase(ReachableShadowNodes.begin()+i);
        ShadowNodes.erase(ShadowNodes.begin()+i);   // Remove node entry
        --i;  // Don't skip the next node.
        LocalChange = true;
      }

    for (unsigned i = 0; i != AllocNodes.size(); ++i)
      if (!ReachableAllocNodes[i]) {
        // Track all unreachable nodes...
#if DEBUG_NODE_ELIMINATE
        cerr << "Unreachable node eliminated:\n";
        AllocNodes[i]->print(cerr);
#endif
        AllocNodes[i]->removeAllIncomingEdges();
        delete AllocNodes[i];

        // Remove from reachable...
        ReachableAllocNodes.erase(ReachableAllocNodes.begin()+i);
        AllocNodes.erase(AllocNodes.begin()+i);   // Remove node entry
        --i;  // Don't skip the next node.
        LocalChange = true;
      }

    if (!LocalChange) return Changed;      // No more dead nodes...

    Changed = true;
  }
}
<|endoftext|>


<commit_before>#pragma once

#include "flag_argument.hxx"

namespace cl
{
	class help_argument /* Special argument that is used to trigger help display */
		: public flag_argument
	{
		using Tthis = help_argument;
		using Tbase = flag_argument;

		public:
			template< typename... Ttags >
			help_argument(Ttags&&... p_tags)
				: Tbase{ ::std::forward<Ttags>(p_tags)... }
			{
			}
	};
}
<commit_msg>Set default values for help_argument<commit_after>#pragma once

#include "tags.hxx"
#include "flag_argument.hxx"

namespace cl
{
	class help_argument /* Special argument that is used to trigger help display */
		: public flag_argument
	{
		using Tthis = help_argument;
		using Tbase = flag_argument;

		public:
			template< typename... Ttags >
			help_argument(Ttags&&... p_tags)
				: 	Tbase{	cl::description("Display this help text"),
							cl::long_name("help"),
							cl::short_name('h'),
							::std::forward<Ttags>(p_tags)...
					}
			{
			}
	};
}
<|endoftext|>


<commit_before>#ifndef RBX_STATE_HPP
#define RBX_STATE_HPP

namespace rubinius {
  class VM;
  class ManagedThread;
  class ThreadState;
  class SharedState;

  class State {
    VM* vm_;
    SharedState& shared_;

  public:
    State(VM* vm)
      : vm_(vm)
      , shared_(vm->shared)
    {}

    VM* vm() {
      return vm_;
    }

    ManagedThread* thread() {
      return (ManagedThread*)vm_;
    }

    Object* raise_exception(Exception* exc) {
      vm_->thread_state()->raise_exception(exc);
      return 0;
    }

    void set_call_frame(CallFrame* cf) {
      vm_->set_call_frame(cf);
    }

    Globals& globals() {
      return shared_.globals;
    }

    Symbol* symbol(const char* str) {
      return vm_->symbol(str);
    }

    Symbol* symbol(std::string str) {
      return vm_->symbol(str);
    }

    Symbol* symbol(String* str) {
      return vm_->symbol(str);
    }

    template <class T>
      T* new_object(Class *cls) {
        return reinterpret_cast<T*>(vm_->new_object_typed(cls, sizeof(T), T::type));
      }

    ThreadState* thread_state() {
      return vm_->thread_state();
    }

    ObjectMemory* memory() {
      return shared_.memory();
    }

    SharedState& shared() {
      return shared_;
    }

    bool detect_stack_condition(void* end) {
      return vm_->detect_stack_condition(end);
    }

    bool check_async(CallFrame* call_frame) {
      if(vm_->check_local_interrupts) {
        return process_async(call_frame);
      }
      return true;
    }

    void raise_stack_error(CallFrame* call_frame);

    bool check_stack(CallFrame* call_frame, void* end) {
      // @TODO assumes stack growth direction
      if(unlikely(reinterpret_cast<uintptr_t>(end) < vm_->stack_limit_)) {
        raise_stack_error(call_frame);
        return false;
      }

      return true;
    }

    bool process_async(CallFrame* call_frame);
    void check_exception(CallFrame* call_frame);
    bool check_interrupts(GCToken gct, CallFrame* call_frame, void* end);

    gc::Slab& local_slab() {
      return vm_->local_slab();
    }

    bool stop_the_world() WARN_UNUSED {
      return shared_.stop_the_world(vm_);
    };

    void restart_world() {
      shared_.restart_world(vm_);
    }

    void gc_independent() {
      shared_.gc_independent(vm_);
    }

    void gc_dependent() {
      shared_.gc_dependent(vm_);
    }

    void checkpoint(GCToken gct, CallFrame* call_frame) {
      vm_->set_call_frame(call_frame);
      gc_checkpoint(gct, call_frame);
      shared_.checkpoint(vm_);
    }

    void gc_checkpoint(GCToken gct, CallFrame* frame) {
      if(unlikely(shared_.check_gc_p())) {
        vm_->collect_maybe(gct, frame);
      }
    }

    void lock() {
      vm_->lock(vm_);
    }

    void unlock() {
      vm_->unlock(vm_);
    }

  };
}

#endif
<commit_msg>Go independent before locking to prevent deadlocking<commit_after>#ifndef RBX_STATE_HPP
#define RBX_STATE_HPP

namespace rubinius {
  class VM;
  class ManagedThread;
  class ThreadState;
  class SharedState;

  class State {
    VM* vm_;
    SharedState& shared_;

  public:
    State(VM* vm)
      : vm_(vm)
      , shared_(vm->shared)
    {}

    VM* vm() {
      return vm_;
    }

    ManagedThread* thread() {
      return (ManagedThread*)vm_;
    }

    Object* raise_exception(Exception* exc) {
      vm_->thread_state()->raise_exception(exc);
      return 0;
    }

    void set_call_frame(CallFrame* cf) {
      vm_->set_call_frame(cf);
    }

    Globals& globals() {
      return shared_.globals;
    }

    Symbol* symbol(const char* str) {
      return vm_->symbol(str);
    }

    Symbol* symbol(std::string str) {
      return vm_->symbol(str);
    }

    Symbol* symbol(String* str) {
      return vm_->symbol(str);
    }

    template <class T>
      T* new_object(Class *cls) {
        return reinterpret_cast<T*>(vm_->new_object_typed(cls, sizeof(T), T::type));
      }

    ThreadState* thread_state() {
      return vm_->thread_state();
    }

    ObjectMemory* memory() {
      return shared_.memory();
    }

    SharedState& shared() {
      return shared_;
    }

    bool detect_stack_condition(void* end) {
      return vm_->detect_stack_condition(end);
    }

    bool check_async(CallFrame* call_frame) {
      if(vm_->check_local_interrupts) {
        return process_async(call_frame);
      }
      return true;
    }

    void raise_stack_error(CallFrame* call_frame);

    bool check_stack(CallFrame* call_frame, void* end) {
      // @TODO assumes stack growth direction
      if(unlikely(reinterpret_cast<uintptr_t>(end) < vm_->stack_limit_)) {
        raise_stack_error(call_frame);
        return false;
      }

      return true;
    }

    bool process_async(CallFrame* call_frame);
    void check_exception(CallFrame* call_frame);
    bool check_interrupts(GCToken gct, CallFrame* call_frame, void* end);

    gc::Slab& local_slab() {
      return vm_->local_slab();
    }

    bool stop_the_world() WARN_UNUSED {
      return shared_.stop_the_world(vm_);
    };

    void restart_world() {
      shared_.restart_world(vm_);
    }

    void gc_independent() {
      shared_.gc_independent(vm_);
    }

    void gc_dependent() {
      shared_.gc_dependent(vm_);
    }

    void checkpoint(GCToken gct, CallFrame* call_frame) {
      vm_->set_call_frame(call_frame);
      gc_checkpoint(gct, call_frame);
      shared_.checkpoint(vm_);
    }

    void gc_checkpoint(GCToken gct, CallFrame* frame) {
      if(unlikely(shared_.check_gc_p())) {
        vm_->collect_maybe(gct, frame);
      }
    }

    void lock() {
      gc_independent();
      vm_->lock(vm_);
      gc_dependent();
    }

    void unlock() {
      vm_->unlock(vm_);
    }

  };
}

#endif
<|endoftext|>


<commit_before>//===- TopDownClosure.cpp - Compute the top-down interprocedure closure ---===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the TDDataStructures class, which represents the
// Top-down Interprocedural closure of the data structure graph over the
// program.  This is useful (but not strictly necessary?) for applications
// like pointer analysis.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/DataStructure.h"
#include "llvm/Module.h"
#include "llvm/DerivedTypes.h"
#include "Support/Debug.h"
#include "Support/Statistic.h"
#include "DSCallSiteIterator.h"

namespace {
  RegisterAnalysis<TDDataStructures>   // Register the pass
  Y("tddatastructure", "Top-down Data Structure Analysis");

  Statistic<> NumTDInlines("tddatastructures", "Number of graphs inlined");
}

void TDDataStructures::markReachableFunctionsExternallyAccessible(DSNode *N,
                                                   hash_set<DSNode*> &Visited) {
  if (!N || Visited.count(N)) return;
  Visited.insert(N);

  for (unsigned i = 0, e = N->getNumLinks(); i != e; ++i) {
    DSNodeHandle &NH = N->getLink(i*N->getPointerSize());
    if (DSNode *NN = NH.getNode()) {
      const std::vector<GlobalValue*> &Globals = NN->getGlobals();
      for (unsigned G = 0, e = Globals.size(); G != e; ++G)
        if (Function *F = dyn_cast<Function>(Globals[G]))
          ArgsRemainIncomplete.insert(F);

      markReachableFunctionsExternallyAccessible(NN, Visited);
    }
  }
}

// run - Calculate the top down data structure graphs for each function in the
// program.
//
bool TDDataStructures::run(Module &M) {
  BUDataStructures &BU = getAnalysis<BUDataStructures>();
  GlobalsGraph = new DSGraph(BU.getGlobalsGraph());
  GlobalsGraph->setPrintAuxCalls();

  // Figure out which functions must not mark their arguments complete because
  // they are accessible outside this compilation unit.  Currently, these
  // arguments are functions which are reachable by global variables in the
  // globals graph.
  const DSGraph::ScalarMapTy &GGSM = GlobalsGraph->getScalarMap();
  hash_set<DSNode*> Visited;
  for (DSGraph::ScalarMapTy::const_iterator I = GGSM.begin(), E = GGSM.end();
       I != E; ++I)
    if (isa<GlobalValue>(I->first))
      markReachableFunctionsExternallyAccessible(I->second.getNode(), Visited);

  // Loop over unresolved call nodes.  Any functions passed into (but not
  // returned!?) from unresolvable call nodes may be invoked outside of the
  // current module.
  const std::vector<DSCallSite> &Calls = GlobalsGraph->getAuxFunctionCalls();
  for (unsigned i = 0, e = Calls.size(); i != e; ++i) {
    const DSCallSite &CS = Calls[i];
    for (unsigned arg = 0, e = CS.getNumPtrArgs(); arg != e; ++arg)
      markReachableFunctionsExternallyAccessible(CS.getPtrArg(arg).getNode(),
                                                 Visited);
  }
  Visited.clear();

  // Functions without internal linkage also have unknown incoming arguments!
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
    if (!I->isExternal() && !I->hasInternalLinkage())
      ArgsRemainIncomplete.insert(I);

  // We want to traverse the call graph in reverse post-order.  To do this, we
  // calculate a post-order traversal, then reverse it.
  hash_set<DSGraph*> VisitedGraph;
  std::vector<DSGraph*> PostOrder;
  const BUDataStructures::ActualCalleesTy &ActualCallees =
    getAnalysis<BUDataStructures>().getActualCallees();

  // Calculate top-down from main...
  if (Function *F = M.getMainFunction())
    ComputePostOrder(*F, VisitedGraph, PostOrder, ActualCallees);

  // Next calculate the graphs for each unreachable function...
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
    ComputePostOrder(*I, VisitedGraph, PostOrder, ActualCallees);

  VisitedGraph.clear();   // Release memory!

  // Visit each of the graphs in reverse post-order now!
  while (!PostOrder.empty()) {
    inlineGraphIntoCallees(*PostOrder.back());
    PostOrder.pop_back();
  }

  ArgsRemainIncomplete.clear();
  return false;
}

DSGraph &TDDataStructures::getOrCreateDSGraph(Function &F) {
  DSGraph *&G = DSInfo[&F];
  if (G == 0) { // Not created yet?  Clone BU graph...
    G = new DSGraph(getAnalysis<BUDataStructures>().getDSGraph(F));
    G->getAuxFunctionCalls().clear();
    G->setPrintAuxCalls();
    G->setGlobalsGraph(GlobalsGraph);
  }
  return *G;
}

void TDDataStructures::ComputePostOrder(Function &F,hash_set<DSGraph*> &Visited,
                                        std::vector<DSGraph*> &PostOrder,
                      const BUDataStructures::ActualCalleesTy &ActualCallees) {
  if (F.isExternal()) return;
  DSGraph &G = getOrCreateDSGraph(F);
  if (Visited.count(&G)) return;
  Visited.insert(&G);

  // Recursively traverse all of the callee graphs.
  const std::vector<DSCallSite> &FunctionCalls = G.getFunctionCalls();

  for (unsigned i = 0, e = FunctionCalls.size(); i != e; ++i) {
    Instruction *CallI = FunctionCalls[i].getCallSite().getInstruction();
    std::pair<BUDataStructures::ActualCalleesTy::const_iterator,
      BUDataStructures::ActualCalleesTy::const_iterator>
         IP = ActualCallees.equal_range(CallI);

    for (BUDataStructures::ActualCalleesTy::const_iterator I = IP.first;
         I != IP.second; ++I)
      ComputePostOrder(*I->second, Visited, PostOrder, ActualCallees);
  }

  PostOrder.push_back(&G);
}

// releaseMemory - If the pass pipeline is done with this pass, we can release
// our memory... here...
//
// FIXME: This should be releaseMemory and will work fine, except that LoadVN
// has no way to extend the lifetime of the pass, which screws up ds-aa.
//
void TDDataStructures::releaseMyMemory() {
  for (hash_map<Function*, DSGraph*>::iterator I = DSInfo.begin(),
         E = DSInfo.end(); I != E; ++I) {
    I->second->getReturnNodes().erase(I->first);
    if (I->second->getReturnNodes().empty())
      delete I->second;
  }

  // Empty map so next time memory is released, data structures are not
  // re-deleted.
  DSInfo.clear();
  delete GlobalsGraph;
  GlobalsGraph = 0;
}

void TDDataStructures::inlineGraphIntoCallees(DSGraph &Graph) {
  // Recompute the Incomplete markers and eliminate unreachable nodes.
  Graph.removeTriviallyDeadNodes();
  Graph.maskIncompleteMarkers();

  // If any of the functions has incomplete incoming arguments, don't mark any
  // of them as complete.
  bool HasIncompleteArgs = false;
  const DSGraph::ReturnNodesTy &GraphReturnNodes = Graph.getReturnNodes();
  for (DSGraph::ReturnNodesTy::const_iterator I = GraphReturnNodes.begin(),
         E = GraphReturnNodes.end(); I != E; ++I)
    if (ArgsRemainIncomplete.count(I->first)) {
      HasIncompleteArgs = true;
      break;
    }

  // Now fold in the necessary globals from the GlobalsGraph.  A global G
  // must be folded in if it exists in the current graph (i.e., is not dead)
  // and it was not inlined from any of my callers.  If it was inlined from
  // a caller, it would have been fully consistent with the GlobalsGraph
  // in the caller so folding in is not necessary.  Otherwise, this node came
  // solely from this function's BU graph and so has to be made consistent.
  //
  Graph.updateFromGlobalGraph();

  // Recompute the Incomplete markers.  Depends on whether args are complete
  unsigned Flags
    = HasIncompleteArgs ? DSGraph::MarkFormalArgs : DSGraph::IgnoreFormalArgs;
  Graph.markIncompleteNodes(Flags | DSGraph::IgnoreGlobals);

  // Delete dead nodes.  Treat globals that are unreachable as dead also.
  Graph.removeDeadNodes(DSGraph::RemoveUnreachableGlobals);

  // We are done with computing the current TD Graph! Now move on to
  // inlining the current graph into the graphs for its callees, if any.
  //
  const std::vector<DSCallSite> &FunctionCalls = Graph.getFunctionCalls();
  if (FunctionCalls.empty()) {
    DEBUG(std::cerr << "  [TD] No callees for: " << Graph.getFunctionNames()
                    << "\n");
    return;
  }

  // Now that we have information about all of the callees, propagate the
  // current graph into the callees.  Clone only the reachable subgraph at
  // each call-site, not the entire graph (even though the entire graph
  // would be cloned only once, this should still be better on average).
  //
  DEBUG(std::cerr << "  [TD] Inlining '" << Graph.getFunctionNames() <<"' into "
                  << FunctionCalls.size() << " call nodes.\n");

  const BUDataStructures::ActualCalleesTy &ActualCallees =
    getAnalysis<BUDataStructures>().getActualCallees();

  // Loop over all the call sites and all the callees at each call site.
  // Clone and merge the reachable subgraph from the call into callee's graph.
  //
  for (unsigned i = 0, e = FunctionCalls.size(); i != e; ++i) {
    Instruction *CallI = FunctionCalls[i].getCallSite().getInstruction();
    // For each function in the invoked function list at this call site...
    std::pair<BUDataStructures::ActualCalleesTy::const_iterator,
      BUDataStructures::ActualCalleesTy::const_iterator>
          IP = ActualCallees.equal_range(CallI);

    // Multiple callees may have the same graph, so try to inline and merge
    // only once for each <callSite,calleeGraph> pair, not once for each
    // <callSite,calleeFunction> pair; the latter will be correct but slower.
    hash_set<DSGraph*> GraphsSeen;

    // Loop over each actual callee at this call site
    for (BUDataStructures::ActualCalleesTy::const_iterator I = IP.first;
         I != IP.second; ++I) {
      DSGraph& CalleeGraph = getDSGraph(*I->second);
      assert(&CalleeGraph != &Graph && "TD need not inline graph into self!");

      // if this callee graph is already done at this site, skip this callee
      if (GraphsSeen.find(&CalleeGraph) != GraphsSeen.end())
        continue;
      GraphsSeen.insert(&CalleeGraph);

      // Get the root nodes for cloning the reachable subgraph into each callee:
      // -- all global nodes that appear in both the caller and the callee
      // -- return value at this call site, if any
      // -- actual arguments passed at this call site
      // -- callee node at this call site, if this is an indirect call (this may
      //    not be needed for merging, but allows us to create CS and therefore
      //    simplify the merging below).
      hash_set<const DSNode*> RootNodeSet;
      for (DSGraph::ScalarMapTy::const_iterator
             SI = CalleeGraph.getScalarMap().begin(),
             SE = CalleeGraph.getScalarMap().end(); SI != SE; ++SI)
        if (GlobalValue* GV = dyn_cast<GlobalValue>(SI->first)) {
          DSGraph::ScalarMapTy::const_iterator GI=Graph.getScalarMap().find(GV);
          if (GI != Graph.getScalarMap().end())
            RootNodeSet.insert(GI->second.getNode());
        }

      if (const DSNode* RetNode = FunctionCalls[i].getRetVal().getNode())
        RootNodeSet.insert(RetNode);

      for (unsigned j=0, N=FunctionCalls[i].getNumPtrArgs(); j < N; ++j)
        if (const DSNode* ArgTarget = FunctionCalls[i].getPtrArg(j).getNode())
          RootNodeSet.insert(ArgTarget);

      if (FunctionCalls[i].isIndirectCall())
        RootNodeSet.insert(FunctionCalls[i].getCalleeNode());

      DEBUG(std::cerr << "     [TD] Resolving arguments for callee graph '"
            << CalleeGraph.getFunctionNames()
            << "': " << I->second->getFunctionType()->getNumParams()
            << " args\n          at call site (DSCallSite*) 0x"
            << &FunctionCalls[i] << "\n");

      DSGraph::NodeMapTy NodeMapInCallee; // map from nodes to clones in callee
      DSGraph::NodeMapTy CompletedMap;    // unused map for nodes not to do
      CalleeGraph.cloneReachableSubgraph(Graph, RootNodeSet,
                                         NodeMapInCallee, CompletedMap,
                                         DSGraph::StripModRefBits |
                                         DSGraph::KeepAllocaBit);

      // Transform our call site info into the cloned version for CalleeGraph
      DSCallSite CS(FunctionCalls[i], NodeMapInCallee);

      // Get the formal argument and return nodes for the called function
      // and merge them with the cloned subgraph.  Global nodes were merged
      // already by cloneReachableSubgraph() above.
      CalleeGraph.getCallSiteForArguments(*I->second).mergeWith(CS);

      ++NumTDInlines;
    }
  }

  DEBUG(std::cerr << "  [TD] Done inlining into callees for: "
        << Graph.getFunctionNames() << " [" << Graph.getGraphSize() << "+"
        << Graph.getFunctionCalls().size() << "]\n");
}

<commit_msg>This doesn't use DSCallSiteIterator<commit_after>//===- TopDownClosure.cpp - Compute the top-down interprocedure closure ---===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the TDDataStructures class, which represents the
// Top-down Interprocedural closure of the data structure graph over the
// program.  This is useful (but not strictly necessary?) for applications
// like pointer analysis.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/DataStructure.h"
#include "llvm/Module.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Analysis/DSGraph.h"
#include "Support/Debug.h"
#include "Support/Statistic.h"

namespace {
  RegisterAnalysis<TDDataStructures>   // Register the pass
  Y("tddatastructure", "Top-down Data Structure Analysis");

  Statistic<> NumTDInlines("tddatastructures", "Number of graphs inlined");
}

void TDDataStructures::markReachableFunctionsExternallyAccessible(DSNode *N,
                                                   hash_set<DSNode*> &Visited) {
  if (!N || Visited.count(N)) return;
  Visited.insert(N);

  for (unsigned i = 0, e = N->getNumLinks(); i != e; ++i) {
    DSNodeHandle &NH = N->getLink(i*N->getPointerSize());
    if (DSNode *NN = NH.getNode()) {
      const std::vector<GlobalValue*> &Globals = NN->getGlobals();
      for (unsigned G = 0, e = Globals.size(); G != e; ++G)
        if (Function *F = dyn_cast<Function>(Globals[G]))
          ArgsRemainIncomplete.insert(F);

      markReachableFunctionsExternallyAccessible(NN, Visited);
    }
  }
}

// run - Calculate the top down data structure graphs for each function in the
// program.
//
bool TDDataStructures::run(Module &M) {
  BUDataStructures &BU = getAnalysis<BUDataStructures>();
  GlobalsGraph = new DSGraph(BU.getGlobalsGraph());
  GlobalsGraph->setPrintAuxCalls();

  // Figure out which functions must not mark their arguments complete because
  // they are accessible outside this compilation unit.  Currently, these
  // arguments are functions which are reachable by global variables in the
  // globals graph.
  const DSGraph::ScalarMapTy &GGSM = GlobalsGraph->getScalarMap();
  hash_set<DSNode*> Visited;
  for (DSGraph::ScalarMapTy::const_iterator I = GGSM.begin(), E = GGSM.end();
       I != E; ++I)
    if (isa<GlobalValue>(I->first))
      markReachableFunctionsExternallyAccessible(I->second.getNode(), Visited);

  // Loop over unresolved call nodes.  Any functions passed into (but not
  // returned!?) from unresolvable call nodes may be invoked outside of the
  // current module.
  const std::vector<DSCallSite> &Calls = GlobalsGraph->getAuxFunctionCalls();
  for (unsigned i = 0, e = Calls.size(); i != e; ++i) {
    const DSCallSite &CS = Calls[i];
    for (unsigned arg = 0, e = CS.getNumPtrArgs(); arg != e; ++arg)
      markReachableFunctionsExternallyAccessible(CS.getPtrArg(arg).getNode(),
                                                 Visited);
  }
  Visited.clear();

  // Functions without internal linkage also have unknown incoming arguments!
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
    if (!I->isExternal() && !I->hasInternalLinkage())
      ArgsRemainIncomplete.insert(I);

  // We want to traverse the call graph in reverse post-order.  To do this, we
  // calculate a post-order traversal, then reverse it.
  hash_set<DSGraph*> VisitedGraph;
  std::vector<DSGraph*> PostOrder;
  const BUDataStructures::ActualCalleesTy &ActualCallees =
    getAnalysis<BUDataStructures>().getActualCallees();

  // Calculate top-down from main...
  if (Function *F = M.getMainFunction())
    ComputePostOrder(*F, VisitedGraph, PostOrder, ActualCallees);

  // Next calculate the graphs for each unreachable function...
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
    ComputePostOrder(*I, VisitedGraph, PostOrder, ActualCallees);

  VisitedGraph.clear();   // Release memory!

  // Visit each of the graphs in reverse post-order now!
  while (!PostOrder.empty()) {
    inlineGraphIntoCallees(*PostOrder.back());
    PostOrder.pop_back();
  }

  ArgsRemainIncomplete.clear();
  return false;
}

DSGraph &TDDataStructures::getOrCreateDSGraph(Function &F) {
  DSGraph *&G = DSInfo[&F];
  if (G == 0) { // Not created yet?  Clone BU graph...
    G = new DSGraph(getAnalysis<BUDataStructures>().getDSGraph(F));
    G->getAuxFunctionCalls().clear();
    G->setPrintAuxCalls();
    G->setGlobalsGraph(GlobalsGraph);
  }
  return *G;
}

void TDDataStructures::ComputePostOrder(Function &F,hash_set<DSGraph*> &Visited,
                                        std::vector<DSGraph*> &PostOrder,
                      const BUDataStructures::ActualCalleesTy &ActualCallees) {
  if (F.isExternal()) return;
  DSGraph &G = getOrCreateDSGraph(F);
  if (Visited.count(&G)) return;
  Visited.insert(&G);

  // Recursively traverse all of the callee graphs.
  const std::vector<DSCallSite> &FunctionCalls = G.getFunctionCalls();

  for (unsigned i = 0, e = FunctionCalls.size(); i != e; ++i) {
    Instruction *CallI = FunctionCalls[i].getCallSite().getInstruction();
    std::pair<BUDataStructures::ActualCalleesTy::const_iterator,
      BUDataStructures::ActualCalleesTy::const_iterator>
         IP = ActualCallees.equal_range(CallI);

    for (BUDataStructures::ActualCalleesTy::const_iterator I = IP.first;
         I != IP.second; ++I)
      ComputePostOrder(*I->second, Visited, PostOrder, ActualCallees);
  }

  PostOrder.push_back(&G);
}

// releaseMemory - If the pass pipeline is done with this pass, we can release
// our memory... here...
//
// FIXME: This should be releaseMemory and will work fine, except that LoadVN
// has no way to extend the lifetime of the pass, which screws up ds-aa.
//
void TDDataStructures::releaseMyMemory() {
  for (hash_map<Function*, DSGraph*>::iterator I = DSInfo.begin(),
         E = DSInfo.end(); I != E; ++I) {
    I->second->getReturnNodes().erase(I->first);
    if (I->second->getReturnNodes().empty())
      delete I->second;
  }

  // Empty map so next time memory is released, data structures are not
  // re-deleted.
  DSInfo.clear();
  delete GlobalsGraph;
  GlobalsGraph = 0;
}

void TDDataStructures::inlineGraphIntoCallees(DSGraph &Graph) {
  // Recompute the Incomplete markers and eliminate unreachable nodes.
  Graph.removeTriviallyDeadNodes();
  Graph.maskIncompleteMarkers();

  // If any of the functions has incomplete incoming arguments, don't mark any
  // of them as complete.
  bool HasIncompleteArgs = false;
  const DSGraph::ReturnNodesTy &GraphReturnNodes = Graph.getReturnNodes();
  for (DSGraph::ReturnNodesTy::const_iterator I = GraphReturnNodes.begin(),
         E = GraphReturnNodes.end(); I != E; ++I)
    if (ArgsRemainIncomplete.count(I->first)) {
      HasIncompleteArgs = true;
      break;
    }

  // Now fold in the necessary globals from the GlobalsGraph.  A global G
  // must be folded in if it exists in the current graph (i.e., is not dead)
  // and it was not inlined from any of my callers.  If it was inlined from
  // a caller, it would have been fully consistent with the GlobalsGraph
  // in the caller so folding in is not necessary.  Otherwise, this node came
  // solely from this function's BU graph and so has to be made consistent.
  //
  Graph.updateFromGlobalGraph();

  // Recompute the Incomplete markers.  Depends on whether args are complete
  unsigned Flags
    = HasIncompleteArgs ? DSGraph::MarkFormalArgs : DSGraph::IgnoreFormalArgs;
  Graph.markIncompleteNodes(Flags | DSGraph::IgnoreGlobals);

  // Delete dead nodes.  Treat globals that are unreachable as dead also.
  Graph.removeDeadNodes(DSGraph::RemoveUnreachableGlobals);

  // We are done with computing the current TD Graph! Now move on to
  // inlining the current graph into the graphs for its callees, if any.
  //
  const std::vector<DSCallSite> &FunctionCalls = Graph.getFunctionCalls();
  if (FunctionCalls.empty()) {
    DEBUG(std::cerr << "  [TD] No callees for: " << Graph.getFunctionNames()
                    << "\n");
    return;
  }

  // Now that we have information about all of the callees, propagate the
  // current graph into the callees.  Clone only the reachable subgraph at
  // each call-site, not the entire graph (even though the entire graph
  // would be cloned only once, this should still be better on average).
  //
  DEBUG(std::cerr << "  [TD] Inlining '" << Graph.getFunctionNames() <<"' into "
                  << FunctionCalls.size() << " call nodes.\n");

  const BUDataStructures::ActualCalleesTy &ActualCallees =
    getAnalysis<BUDataStructures>().getActualCallees();

  // Loop over all the call sites and all the callees at each call site.
  // Clone and merge the reachable subgraph from the call into callee's graph.
  //
  for (unsigned i = 0, e = FunctionCalls.size(); i != e; ++i) {
    Instruction *CallI = FunctionCalls[i].getCallSite().getInstruction();
    // For each function in the invoked function list at this call site...
    std::pair<BUDataStructures::ActualCalleesTy::const_iterator,
      BUDataStructures::ActualCalleesTy::const_iterator>
          IP = ActualCallees.equal_range(CallI);

    // Multiple callees may have the same graph, so try to inline and merge
    // only once for each <callSite,calleeGraph> pair, not once for each
    // <callSite,calleeFunction> pair; the latter will be correct but slower.
    hash_set<DSGraph*> GraphsSeen;

    // Loop over each actual callee at this call site
    for (BUDataStructures::ActualCalleesTy::const_iterator I = IP.first;
         I != IP.second; ++I) {
      DSGraph& CalleeGraph = getDSGraph(*I->second);
      assert(&CalleeGraph != &Graph && "TD need not inline graph into self!");

      // if this callee graph is already done at this site, skip this callee
      if (GraphsSeen.find(&CalleeGraph) != GraphsSeen.end())
        continue;
      GraphsSeen.insert(&CalleeGraph);

      // Get the root nodes for cloning the reachable subgraph into each callee:
      // -- all global nodes that appear in both the caller and the callee
      // -- return value at this call site, if any
      // -- actual arguments passed at this call site
      // -- callee node at this call site, if this is an indirect call (this may
      //    not be needed for merging, but allows us to create CS and therefore
      //    simplify the merging below).
      hash_set<const DSNode*> RootNodeSet;
      for (DSGraph::ScalarMapTy::const_iterator
             SI = CalleeGraph.getScalarMap().begin(),
             SE = CalleeGraph.getScalarMap().end(); SI != SE; ++SI)
        if (GlobalValue* GV = dyn_cast<GlobalValue>(SI->first)) {
          DSGraph::ScalarMapTy::const_iterator GI=Graph.getScalarMap().find(GV);
          if (GI != Graph.getScalarMap().end())
            RootNodeSet.insert(GI->second.getNode());
        }

      if (const DSNode* RetNode = FunctionCalls[i].getRetVal().getNode())
        RootNodeSet.insert(RetNode);

      for (unsigned j=0, N=FunctionCalls[i].getNumPtrArgs(); j < N; ++j)
        if (const DSNode* ArgTarget = FunctionCalls[i].getPtrArg(j).getNode())
          RootNodeSet.insert(ArgTarget);

      if (FunctionCalls[i].isIndirectCall())
        RootNodeSet.insert(FunctionCalls[i].getCalleeNode());

      DEBUG(std::cerr << "     [TD] Resolving arguments for callee graph '"
            << CalleeGraph.getFunctionNames()
            << "': " << I->second->getFunctionType()->getNumParams()
            << " args\n          at call site (DSCallSite*) 0x"
            << &FunctionCalls[i] << "\n");

      DSGraph::NodeMapTy NodeMapInCallee; // map from nodes to clones in callee
      DSGraph::NodeMapTy CompletedMap;    // unused map for nodes not to do
      CalleeGraph.cloneReachableSubgraph(Graph, RootNodeSet,
                                         NodeMapInCallee, CompletedMap,
                                         DSGraph::StripModRefBits |
                                         DSGraph::KeepAllocaBit);

      // Transform our call site info into the cloned version for CalleeGraph
      DSCallSite CS(FunctionCalls[i], NodeMapInCallee);

      // Get the formal argument and return nodes for the called function
      // and merge them with the cloned subgraph.  Global nodes were merged
      // already by cloneReachableSubgraph() above.
      CalleeGraph.getCallSiteForArguments(*I->second).mergeWith(CS);

      ++NumTDInlines;
    }
  }

  DEBUG(std::cerr << "  [TD] Done inlining into callees for: "
        << Graph.getFunctionNames() << " [" << Graph.getGraphSize() << "+"
        << Graph.getFunctionCalls().size() << "]\n");
}

<|endoftext|>


<commit_before>#pragma once
/**
	@file
	@brief measure exec time of function
	@author MITSUNARI Shigeo
*/
#if defined(_MSC_VER) && (MSC_VER <= 1500)
	#include <cybozu/inttype.hpp>
#else
	#include <stdint.h>
#endif
#include <stdio.h>

#if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || defined(__x86_64__)
	#define CYBOZU_BENCH_USE_RDTSC
#endif
#ifdef CYBOZU_BENCH_USE_RDTSC
	#ifdef _MSC_VER
		#include <intrin.h>
	#endif
#else
	#include <time.h>
	#include <assert.h>
#endif

#ifndef CYBOZU_UNUSED
	#ifdef __GNUC__
		#define CYBOZU_UNUSED __attribute__((unused))
	#else
		#define CYBOZU_UNUSED
	#endif
#endif

namespace cybozu {

#ifdef CYBOZU_BENCH_USE_RDTSC
class CpuClock {
public:
	static inline uint64_t getRdtsc()
	{
#ifdef _MSC_VER
		return __rdtsc();
#else
		unsigned int eax, edx;
		__asm__ volatile("rdtsc" : "=a"(eax), "=d"(edx));
		return ((uint64_t)edx << 32) | eax;
#endif
	}
	CpuClock()
		: clock_(0)
		, count_(0)
	{
	}
	void begin()
	{
		clock_ -= getRdtsc();
	}
	void end()
	{
		clock_ += getRdtsc();
		count_++;
	}
	int getCount() const { return count_; }
	uint64_t getClock() const { return clock_; }
	void clear() { count_ = 0; clock_ = 0; }
	void put(const char *msg = 0, int N = 1) const
	{
		double t = getClock() / double(getCount()) / N;
		if (msg && *msg) printf("%s ", msg);
		if (t > 1e6) {
			printf("%7.3fMclk", t * 1e-6);
		} else if (t > 1e3) {
			printf("%7.3fKclk", t * 1e-3);
		} else {
			printf("%6.2f clk", t);
		}
		if (msg && *msg) printf("\n");
	}
	// adhoc constatns for CYBOZU_BENCH
	static const int loopN1 = 1000;
	static const int loopN2 = 1000000;
	static const uint64_t maxClk = (uint64_t)3e8;
private:
	uint64_t clock_;
	int count_;
};
#else
class CpuClock {
	uint64_t startNsec_;
	uint64_t clock_;
	int count_;
	uint64_t getTimeNsec() const
	{
		struct timespec tp;
		int ret CYBOZU_UNUSED = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tp);
		assert(ret == 0);
		return tp.tv_sec * 1000000000 + tp.tv_nsec;
	}
public:
	CpuClock() : startNsec_(0), clock_(0), count_(0) { }
	void begin()
	{
		startNsec_ = getTimeNsec();
	}
	/*
		@note QQQ ; this is not same api as rdtsc version
	*/
	void end()
	{
		uint64_t cur = getTimeNsec();
		clock_ += cur - startNsec_;
		startNsec_ = cur;
		count_++;
	}
	int getCount() const { return count_; }
	uint64_t getClock() const { return clock_; }
	void clear() { startNsec_ = 0; clock_ = 0; count_ = 0; }
	void put(const char *msg = 0, int N = 1) const
	{
		double t = getClock() / double(getCount()) / N;
		if (msg && *msg) printf("%s ", msg);
		if (t > 1) {
			printf("%6.2fmsec", t * 1e-6);
		} else if (t > 1e-3) {
			printf("%6.2fusec", t * 1e-3);
		} else {
			printf("%6.2fnsec", t);
		}
		if (msg && *msg) printf("\n");
	}
	// adhoc constatns for CYBOZU_BENCH
	static const int loopN1 = 1000;
	static const int loopN2 = 1000000;
	static const uint64_t maxClk = (uint64_t)3e8;
};
#endif

namespace bench {

static CpuClock g_clk;
static int CYBOZU_UNUSED g_loopNum;

} // cybozu::bench
/*
	loop counter is automatically determined
	CYBOZU_BENCH(<msg>, <func>, <param1>, <param2>, ...);
	if msg == "" then only set g_clk, g_loopNum
*/
#define CYBOZU_BENCH(msg, func, ...) \
{ \
	const uint64_t _cybozu_maxClk = cybozu::CpuClock::maxClk; \
	cybozu::CpuClock _cybozu_clk; \
	for (int _cybozu_i = 0; _cybozu_i < cybozu::CpuClock::loopN2; _cybozu_i++) { \
		_cybozu_clk.begin(); \
		for (int _cybozu_j = 0; _cybozu_j < cybozu::CpuClock::loopN1; _cybozu_j++) { func(__VA_ARGS__); } \
		_cybozu_clk.end(); \
		if (_cybozu_clk.getClock() > _cybozu_maxClk) break; \
	} \
	if (msg && *msg) _cybozu_clk.put(msg, cybozu::CpuClock::loopN1); \
	cybozu::bench::g_clk = _cybozu_clk; cybozu::bench::g_loopNum = cybozu::CpuClock::loopN1; \
}

/*
	loop counter N is given
	CYBOZU_BENCH_C(<msg>, <counter>, <func>, <param1>, <param2>, ...);
	if msg == "" then only set g_clk, g_loopNum
*/
#define CYBOZU_BENCH_C(msg, _N, func, ...) \
{ \
	cybozu::CpuClock _cybozu_clk; \
	_cybozu_clk.begin(); \
	for (int _cybozu_j = 0; _cybozu_j < _N; _cybozu_j++) { func(__VA_ARGS__); } \
	_cybozu_clk.end(); \
	if (msg && *msg) _cybozu_clk.put(msg, _N); \
	cybozu::bench::g_clk = _cybozu_clk; cybozu::bench::g_loopNum = _N; \
}

} // cybozu
<commit_msg>add CYBOZU_BENCH_T<commit_after>#pragma once
/**
	@file
	@brief measure exec time of function
	@author MITSUNARI Shigeo
*/
#if defined(_MSC_VER) && (MSC_VER <= 1500)
	#include <cybozu/inttype.hpp>
#else
	#include <stdint.h>
#endif
#include <stdio.h>

#if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || defined(__x86_64__)
	#define CYBOZU_BENCH_USE_RDTSC
#endif
#ifdef CYBOZU_BENCH_USE_RDTSC
	#ifdef _MSC_VER
		#include <intrin.h>
	#endif
#else
	#include <time.h>
	#include <assert.h>
#endif

#ifndef CYBOZU_UNUSED
	#ifdef __GNUC__
		#define CYBOZU_UNUSED __attribute__((unused))
	#else
		#define CYBOZU_UNUSED
	#endif
#endif

namespace cybozu {

#ifdef CYBOZU_BENCH_USE_RDTSC
class CpuClock {
public:
	static inline uint64_t getRdtsc()
	{
#ifdef _MSC_VER
		return __rdtsc();
#else
		unsigned int eax, edx;
		__asm__ volatile("rdtsc" : "=a"(eax), "=d"(edx));
		return ((uint64_t)edx << 32) | eax;
#endif
	}
	CpuClock()
		: clock_(0)
		, count_(0)
	{
	}
	void begin()
	{
		clock_ -= getRdtsc();
	}
	void end()
	{
		clock_ += getRdtsc();
		count_++;
	}
	int getCount() const { return count_; }
	uint64_t getClock() const { return clock_; }
	void clear() { count_ = 0; clock_ = 0; }
	void put(const char *msg = 0, int N = 1) const
	{
		double t = getClock() / double(getCount()) / N;
		if (msg && *msg) printf("%s ", msg);
		if (t > 1e6) {
			printf("%7.3fMclk", t * 1e-6);
		} else if (t > 1e3) {
			printf("%7.3fKclk", t * 1e-3);
		} else {
			printf("%6.2f clk", t);
		}
		if (msg && *msg) printf("\n");
	}
	// adhoc constatns for CYBOZU_BENCH
	static const int loopN1 = 1000;
	static const int loopN2 = 1000000;
	static const uint64_t maxClk = (uint64_t)3e8;
private:
	uint64_t clock_;
	int count_;
};
#else
class CpuClock {
	uint64_t startNsec_;
	uint64_t clock_;
	int count_;
	uint64_t getTimeNsec() const
	{
		struct timespec tp;
		int ret CYBOZU_UNUSED = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tp);
		assert(ret == 0);
		return tp.tv_sec * 1000000000 + tp.tv_nsec;
	}
public:
	CpuClock() : startNsec_(0), clock_(0), count_(0) { }
	void begin()
	{
		startNsec_ = getTimeNsec();
	}
	/*
		@note QQQ ; this is not same api as rdtsc version
	*/
	void end()
	{
		uint64_t cur = getTimeNsec();
		clock_ += cur - startNsec_;
		startNsec_ = cur;
		count_++;
	}
	int getCount() const { return count_; }
	uint64_t getClock() const { return clock_; }
	void clear() { startNsec_ = 0; clock_ = 0; count_ = 0; }
	void put(const char *msg = 0, int N = 1) const
	{
		double t = getClock() / double(getCount()) / N;
		if (msg && *msg) printf("%s ", msg);
		if (t > 1) {
			printf("%6.2fmsec", t * 1e-6);
		} else if (t > 1e-3) {
			printf("%6.2fusec", t * 1e-3);
		} else {
			printf("%6.2fnsec", t);
		}
		if (msg && *msg) printf("\n");
	}
	// adhoc constatns for CYBOZU_BENCH
	static const int loopN1 = 1000;
	static const int loopN2 = 1000000;
	static const uint64_t maxClk = (uint64_t)3e8;
};
#endif

namespace bench {

static CpuClock g_clk;
static int CYBOZU_UNUSED g_loopNum;

} // cybozu::bench
/*
	loop counter is automatically determined
	CYBOZU_BENCH(<msg>, <func>, <param1>, <param2>, ...);
	if msg == "" then only set g_clk, g_loopNum
*/
#define CYBOZU_BENCH(msg, func, ...) \
{ \
	const uint64_t _cybozu_maxClk = cybozu::CpuClock::maxClk; \
	cybozu::CpuClock _cybozu_clk; \
	for (int _cybozu_i = 0; _cybozu_i < cybozu::CpuClock::loopN2; _cybozu_i++) { \
		_cybozu_clk.begin(); \
		for (int _cybozu_j = 0; _cybozu_j < cybozu::CpuClock::loopN1; _cybozu_j++) { func(__VA_ARGS__); } \
		_cybozu_clk.end(); \
		if (_cybozu_clk.getClock() > _cybozu_maxClk) break; \
	} \
	if (msg && *msg) _cybozu_clk.put(msg, cybozu::CpuClock::loopN1); \
	cybozu::bench::g_clk = _cybozu_clk; cybozu::bench::g_loopNum = cybozu::CpuClock::loopN1; \
}

/*
	double clk;
	CYBOZU_BENCH_T(clk, <func>, <param1>, <param2>, ...);
	clk is set by CYBOZU_BENCH_T
*/
#define CYBOZU_BENCH_T(clk, func, ...) \
{ \
	const uint64_t _cybozu_maxClk = cybozu::CpuClock::maxClk; \
	cybozu::CpuClock _cybozu_clk; \
	for (int _cybozu_i = 0; _cybozu_i < cybozu::CpuClock::loopN2; _cybozu_i++) { \
		_cybozu_clk.begin(); \
		for (int _cybozu_j = 0; _cybozu_j < cybozu::CpuClock::loopN1; _cybozu_j++) { func(__VA_ARGS__); } \
		_cybozu_clk.end(); \
		if (_cybozu_clk.getClock() > _cybozu_maxClk) break; \
	} \
	clk = _cybozu_clk.getClock() / (double)_cybozu_clk.getCount() / cybozu::CpuClock::loopN1; \
}

/*
	loop counter N is given
	CYBOZU_BENCH_C(<msg>, <counter>, <func>, <param1>, <param2>, ...);
	if msg == "" then only set g_clk, g_loopNum
*/
#define CYBOZU_BENCH_C(msg, _N, func, ...) \
{ \
	cybozu::CpuClock _cybozu_clk; \
	_cybozu_clk.begin(); \
	for (int _cybozu_j = 0; _cybozu_j < _N; _cybozu_j++) { func(__VA_ARGS__); } \
	_cybozu_clk.end(); \
	if (msg && *msg) _cybozu_clk.put(msg, _N); \
	cybozu::bench::g_clk = _cybozu_clk; cybozu::bench::g_loopNum = _N; \
}

} // cybozu
<|endoftext|>


<commit_before>/*
Copyright (c) 2014-2015, Scott Zuyderduyn
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/

//----------------------------------------------------------------------------
// device_ptr.hpp
//
// Smart pointer to device memory.
//
// Author: Scott D. Zuyderduyn, Ph.D. (scott.zuyderduyn@utoronto.ca)
//----------------------------------------------------------------------------

#pragma once
#ifndef ECUDA_DEVICE_PTR_HPP
#define ECUDA_DEVICE_PTR_HPP

//#include <cstddef>
#include "global.hpp"

//#ifdef __CPP11_SUPPORTED__
//#include <memory>
//#endif

namespace ecuda {

/*
template<typename T>
class deleter {
public:
	typedef T element_type;
	typedef T* pointer;
public:
	HOST DEVICE deleter() {}
	HOST DEVICE deleter( const deleter& other ) {}
	HOST DEVICE ~deleter() {}
	HOST inline void operator()( pointer ptr ) { if( ptr ) CUDA_CALL( cudaFree(ptr) ); }
};
*/

///
/// A smart pointer for device memory.
///
/// This class keeps a pointer to allocated device memory and automatically
/// deallocates it when it goes out of scope.  The workings are similar to
/// a C++11 shared_ptr.  Since deallocation can only be done from host code
/// reference counting only occurs within host code.  On the device the pointer
/// is passed around freely without regards to reference counting and will
/// never undergo deallocation.
///
/// Like a typical smart pointer, this class handles deallocation but allocation
/// is performed elsewhere and the pointer to the allocated memory location is
/// passed to the constructor.
///
template<typename T>
class device_ptr {

public:
	typedef T element_type; //!< data type represented in allocated memory
	typedef T* pointer; //!< data type pointer
	typedef T& reference; //!< data type reference
	typedef std::size_t size_type; //!< size type for pointer arithmetic and reference counting
	typedef std::ptrdiff_t difference_type; //!< signed integer type of the result of subtracting two pointers

private:
	pointer ptr; //!< pointer to device memory
	size_type* shared_count; //!< pointer to reference count

public:
	//HOST DEVICE device_ptr() : ptr(NULL) {
	//	#ifndef __CUDA_ARCH__
	//	shared_count = new size_type;
	//	*shared_count = 1;
	//	#endif
	//}
	HOST DEVICE device_ptr( pointer ptr = pointer() ) : ptr(ptr) {
		#ifndef __CUDA_ARCH__
		shared_count = new size_type;
		*shared_count = 1;
		#endif
	}

	HOST DEVICE device_ptr( const device_ptr<T>& src ) : ptr(src.ptr), shared_count(src.shared_count) {
		#ifndef __CUDA_ARCH__
		++(*shared_count);
		#endif
	}

	#ifdef __CPP11_SUPPORTED__
	HOST DEVICE device_ptr( device_ptr<T>&& src ) : ptr(src.ptr), shared_count(src.shared_count) {
		src.ptr = NULL;
		src.shared_count = NULL;
	}
	#endif

	// destroys the smart pointer, if instantiated from the host this will decrement the share count,
	// if instantiated from the device nothing happens, iff. the share count is zero and the smart
	// pointer resides on the host, the underlying device memory will be deallocated.
	HOST DEVICE ~device_ptr() {
		#ifndef __CUDA_ARCH__
		--(*shared_count);
		if( !(*shared_count) ) {
			if( ptr ) CUDA_CALL( cudaFree( ptr ) );
			//deleter<T>()(ptr);
			delete shared_count;
		}
		#endif
	}

	// both host and device can get the pointer itself
	HOST DEVICE inline pointer get() const { return ptr; }
	HOST DEVICE inline operator bool() const { return get() != NULL; }
	HOST DEVICE inline operator pointer() const { return ptr; }

	// only device can dereference the pointer or call for the pointer in the context of acting upon the object
	DEVICE inline reference operator*() const { return *ptr; }
	DEVICE inline pointer   operator->() const { return ptr; }
	DEVICE inline reference operator[]( size_type index ) const { return *(ptr+index); }

	// both host and device can do comparisons on the pointer
	HOST DEVICE inline bool operator==( const device_ptr<T>& other ) const { return ptr == other.ptr; }
	HOST DEVICE inline bool operator!=( const device_ptr<T>& other ) const { return ptr != other.ptr; }
	HOST DEVICE inline bool operator< ( const device_ptr<T>& other ) const { return ptr <  other.ptr; }
	HOST DEVICE inline bool operator> ( const device_ptr<T>& other ) const { return ptr >  other.ptr; }
	HOST DEVICE inline bool operator<=( const device_ptr<T>& other ) const { return ptr <= other.ptr; }
	HOST DEVICE inline bool operator>=( const device_ptr<T>& other ) const { return ptr >= other.ptr; }

	HOST DEVICE inline difference_type operator-( const device_ptr<T>& other ) const { return ptr - other.ptr; }

	HOST device_ptr<T>& operator=( pointer ptr ) {
		~device_ptr();
		this->ptr = ptr;
		shared_count = new size_type;
		*shared_count = 1;
		return *this;
	}

	HOST DEVICE device_ptr<T>& operator=( const device_ptr<T>& other ) {
		#ifndef __CUDA_ARCH__
		~device_ptr();
		#endif
		ptr = other.ptr;
		#ifndef __CUDA_ARCH__
		shared_count = other.shared_count;
		++(*shared_count);
		#endif
		return *this;
	}

};

} // namespace ecuda

#endif
<commit_msg>documenting device_ptr adding additional methods to be more closely related to shared_ptr<commit_after>/*
Copyright (c) 2014-2015, Scott Zuyderduyn
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/

//----------------------------------------------------------------------------
// device_ptr.hpp
//
// Smart pointer to device memory.
//
// Author: Scott D. Zuyderduyn, Ph.D. (scott.zuyderduyn@utoronto.ca)
//----------------------------------------------------------------------------

#pragma once
#ifndef ECUDA_DEVICE_PTR_HPP
#define ECUDA_DEVICE_PTR_HPP

#include "global.hpp"
#include "algorithm.hpp"

namespace ecuda {

///
/// A smart pointer for device memory.
///
/// This class keeps a pointer to allocated device memory and automatically
/// deallocates it when it goes out of scope.  The workings are similar to
/// a C++11 shared_ptr.  Since deallocation can only be done from host code
/// reference counting only occurs within host code.  On the device the pointer
/// is passed around freely without regards to reference counting and will
/// never undergo deallocation.
///
/// Like a typical smart pointer, this class handles deallocation but allocation
/// is performed elsewhere and the pointer to the allocated memory location is
/// passed to the constructor.
///
template<typename T>
class device_ptr {

public:
	typedef T element_type; //!< data type represented in allocated memory
	typedef T* pointer; //!< data type pointer
	typedef T& reference; //!< data type reference
	typedef std::size_t size_type; //!< size type for pointer arithmetic and reference counting
	typedef std::ptrdiff_t difference_type; //!< signed integer type of the result of subtracting two pointers

private:
	pointer ptr; //!< pointer to device memory
	size_type* reference_count; //!< pointer to reference count

public:
	///
	/// \brief Default constructor.
	///
	/// \param ptr A pointer to the allocated block of device memory.
	///
	HOST DEVICE device_ptr( pointer ptr = pointer() ) : ptr(ptr) {
		#ifndef __CUDA_ARCH__
		reference_count = new size_type;
		*reference_count = 1;
		#else
		reference_count = nullptr;
		#endif
	}

	///
	/// \brief Copy constructor.
	///
	/// If called from the host, the reference count is incremented. If called from the device,
	/// the underlying pointer is copied but no change to the reference count occurs.
	///
	/// \param src Another device pointer to be used as source to initialize with.
	///
	HOST DEVICE device_ptr( const device_ptr<T>& src ) : ptr(src.ptr), reference_count(src.reference_count) {
		#ifndef __CUDA_ARCH__
		++(*reference_count);
		#endif
	}

	#ifdef __CPP11_SUPPORTED__
	///
	/// \brief Move constructor.
	///
	/// Constructs the device pointer using move semantics.
	///
	/// \param src Another device pointer whose contents are to be moved.
	///
	HOST DEVICE device_ptr( device_ptr<T>&& src ) : ptr(src.ptr), shared_count(src.shared_count) {
		src.ptr = nullptr;
		#ifndef __CUDA_ARCH__
		src.reference_count = new size_type;
		*(src.reference_count) = 1;
		#else
		src.reference_count = nullptr;
		#endif
	}
	#endif

	///
	/// \brief Destructor.
	///
	/// Destructs the device pointer. If called from host code, the reference count is decremented.
	/// If the reference count becomes zero, the device memory is freed. If called from the device
	/// the object is destroyed but nothing happens to the underlying pointer or reference count.
	///
	HOST DEVICE ~device_ptr() {
		#ifndef __CUDA_ARCH__
		--(*reference_count);
		if( !(*reference_count) ) {
			if( ptr ) CUDA_CALL( cudaFree( ptr ) );
			//deleter<T>()(ptr);
			delete reference_count;
		}
		#endif
	}

	///
	/// \brief Exchanges the contents of *this and other.
	///
	/// \param other device pointer to exchange the contents with
	///
	HOST DEVICE inline void swap( device_ptr& other ) __NOEXCEPT__ {
		#ifdef __CUDA_ARCH__
		ecuda::swap( ptr, other.ptr );
		ecuda::swap( reference_count, other.reference_count );
		#else
		std::swap( ptr, other.ptr );
		std::swap( reference_count, other.reference_count );
		#endif
	}

	HOST DEVICE inline void reset() __NOEXCEPT__ { device_ptr().swap(*this); }
	template<typename U> HOST DEVICE inline void reset( U* p ) __NOEXCEPT__ { device_ptr<T>(p).swap(*this); }

	HOST DEVICE inline pointer get() const { return ptr; }
	DEVICE inline reference operator*() const { return *ptr; }
	DEVICE inline pointer   operator->() const { return ptr; }
	HOST inline size_type use_count() const __NOEXCEPT__ { return reference_count ? *reference_count : 0; }
	HOST inline bool unique() const __NOEXCEPT__ { return use_count() == 1; }
	HOST DEVICE inline operator bool() const { return get() != nullptr; }
	HOST DEVICE inline operator pointer() const { return ptr; }
	template<typename U>
	bool owner_before( const device_ptr<U>& other ) const {
		if( ptr == other.ptr ) return false;
		if( !ptr ) return true;
		if( !other.ptr ) return false;
		return ptr < other.ptr;
	}

	// only device can dereference the pointer or call for the pointer in the context of acting upon the object
	//DEVICE inline reference operator[]( size_type index ) const { return *(ptr+index); }

	// both host and device can do comparisons on the pointer
	HOST DEVICE inline bool operator==( const device_ptr<T>& other ) const { return ptr == other.ptr; }
	HOST DEVICE inline bool operator!=( const device_ptr<T>& other ) const { return ptr != other.ptr; }
	HOST DEVICE inline bool operator< ( const device_ptr<T>& other ) const { return ptr <  other.ptr; }
	HOST DEVICE inline bool operator> ( const device_ptr<T>& other ) const { return ptr >  other.ptr; }
	HOST DEVICE inline bool operator<=( const device_ptr<T>& other ) const { return ptr <= other.ptr; }
	HOST DEVICE inline bool operator>=( const device_ptr<T>& other ) const { return ptr >= other.ptr; }

	HOST DEVICE inline difference_type operator-( const device_ptr<T>& other ) const { return ptr - other.ptr; }

	HOST device_ptr<T>& operator=( pointer p ) {
		~device_ptr();
		ptr = p;
		reference_count = new size_type;
		*reference_count = 1;
		return *this;
	}

	HOST DEVICE device_ptr<T>& operator=( const device_ptr<T>& other ) {
		#ifndef __CUDA_ARCH__
		~device_ptr();
		#endif
		ptr = other.ptr;
		#ifndef __CUDA_ARCH__
		reference_count = other.reference_count;
		++(*reference_count);
		#endif
		return *this;
	}

};

} // namespace ecuda

#endif
<|endoftext|>


<commit_before>/*
 * Graph.cpp
 *
 *  Created on: 18/04/2016
 *      Author: Bernardo
 */

#include "Graph.h"
#include "Vertex.h"
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <cfloat>
#include <queue>

using namespace std;

Graph::Graph() : lastComputedPath(NULL) { }

int Graph::getNumVertex() const {
	return vertexSet.size();
}

vector<Vertex> Graph::getVertexSet() const {
	return vertexSet;
}

bool Graph::addVertex(const Point &in) {

	for (unsigned int i = 0; i < vertexSet.size(); i++) {
		if (vertexSet[i].info == in)
			return false;
	}

	vertexSet.push_back(Vertex(in));
	return true;
}

bool Graph::addEdge(const Point &sourc, const Point &dest, Road* road,
		double distance) {
	int sourceIndex = 0;
	int destIndex = 0;
	bool hasSource, hasDest;

	for (unsigned int i = 0; i < vertexSet.size(); i++) {
		if (vertexSet[i].info == sourc) {
			sourceIndex = i;
			hasSource = true;
		}
	}

	for (unsigned int i = 0; i < vertexSet.size(); i++) {
		if (vertexSet[i].info == dest) {
			destIndex = i;
			hasDest = true;
		}
	}

	if (!hasDest || !hasSource)
		return false;

	Edge* edge = new Edge(&vertexSet[sourceIndex], &vertexSet[destIndex], road, distance);
	vertexSet[sourceIndex].adj.push_back(edge);

	if (road->getTwoWay())
		vertexSet[destIndex].adj.push_back(edge);

	return true;
}

void Graph::printVertexes() const {
	for (unsigned int i = 0; i < vertexSet.size(); i++) {
		cout << vertexSet[i].info << " and have " << vertexSet[i].adj.size()
										<< " edges.\n";
	}
}

list<Vertex*> Graph::getShortestPath(Vertex* source, Vertex* goal) {
	if(lastComputedPath == NULL || source != lastComputedPath)
		computePaths(source);

	list<Vertex*> path = list<Vertex*>();
	Vertex* v = goal;

	if(goal->getDistance() == DBL_MAX)
		return path;

	while(v->previous != NULL) {
		path.push_front(v->previous);
		v = v->previous;
	}

	return path;
}

void Graph::computePaths(Vertex* source) {
	resetPathfinding();

	source->minDistance = 0;

	priority_queue<Vertex*> toBeProcessed = priority_queue<Vertex*>();
	toBeProcessed.push(source);

	while(!toBeProcessed.empty()) {
		Vertex* beingProcessed = toBeProcessed.top();
		toBeProcessed.pop();

		for(unsigned int i = 0; i < beingProcessed->adj.size(); i++) {
			Vertex* dest = beingProcessed->adj[i]->destination;
			double distanceToDest = beingProcessed->adj[i]->distance + beingProcessed->minDistance;

			if(distanceToDest < dest->minDistance) {
				dest->minDistance = distanceToDest;
				dest->previous = beingProcessed;

				toBeProcessed.push(dest);
			}
		}
	}
}

Vertex* Graph::getVertexFromID(unsigned int pointID) {
	for (unsigned int i = 0; i < vertexSet.size(); i++) {
		if (vertexSet[i].info.getId() == pointID)
			return &vertexSet[i];
	}

	return NULL;
}

Vertex* Graph::getVertexFromRoadName(const string &roadName) {

	for(unsigned int i = 0; i < vertexSet.size(); i++){
		for(unsigned int j = 0; j < vertexSet[i].getAdj().size();j++){
			if(vertexSet[i].getAdj()[j]->getRoad()->getName().find(roadName) != string::npos){
				cout<<vertexSet[i].getInfo().getId()<<endl;
				return &vertexSet[i];
			}

			if(vertexSet[i].getInfo().getPOI()==roadName)
				return &vertexSet[i];
		}
	}

	return NULL;
}

void Graph::resetVertexes() {
	for(unsigned int i = 0; i < vertexSet.size(); i++) {
		vertexSet[i].visited = false;
	}
}

void Graph::resetPathfinding() {
	for(unsigned int i = 0; i < vertexSet.size(); i++) {
		vertexSet[i].minDistance = DBL_MAX;
		vertexSet[i].previous = NULL;
	}
}

unsigned int Graph::getVertexSetSize() const {
	return vertexSet.size();
}

Vertex* Graph::getVertexFromIndex(unsigned int index) {
	return &vertexSet[index];
}
<commit_msg>now supports several addresses<commit_after>/*
 * Graph.cpp
 *
 *  Created on: 18/04/2016
 *      Author: Bernardo
 */

#include "Graph.h"
#include "Vertex.h"
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <cfloat>
#include <queue>

using namespace std;

Graph::Graph() : lastComputedPath(NULL) { }

int Graph::getNumVertex() const {
	return vertexSet.size();
}

vector<Vertex> Graph::getVertexSet() const {
	return vertexSet;
}

bool Graph::addVertex(const Point &in) {

	for (unsigned int i = 0; i < vertexSet.size(); i++) {
		if (vertexSet[i].info == in)
			return false;
	}

	vertexSet.push_back(Vertex(in));
	return true;
}

bool Graph::addEdge(const Point &sourc, const Point &dest, Road* road,
		double distance) {
	int sourceIndex = 0;
	int destIndex = 0;
	bool hasSource, hasDest;

	for (unsigned int i = 0; i < vertexSet.size(); i++) {
		if (vertexSet[i].info == sourc) {
			sourceIndex = i;
			hasSource = true;
		}
	}

	for (unsigned int i = 0; i < vertexSet.size(); i++) {
		if (vertexSet[i].info == dest) {
			destIndex = i;
			hasDest = true;
		}
	}

	if (!hasDest || !hasSource)
		return false;

	Edge* edge = new Edge(&vertexSet[sourceIndex], &vertexSet[destIndex], road, distance);
	vertexSet[sourceIndex].adj.push_back(edge);

	if (road->getTwoWay())
		vertexSet[destIndex].adj.push_back(edge);

	return true;
}

void Graph::printVertexes() const {
	for (unsigned int i = 0; i < vertexSet.size(); i++) {
		cout << vertexSet[i].info << " and have " << vertexSet[i].adj.size()
										<< " edges.\n";
	}
}

list<Vertex*> Graph::getShortestPath(Vertex* source, Vertex* goal) {
	if(lastComputedPath == NULL || source != lastComputedPath)
		computePaths(source);

	list<Vertex*> path = list<Vertex*>();
	Vertex* v = goal;

	if(goal->getDistance() == DBL_MAX)
		return path;

	while(v->previous != NULL) {
		path.push_front(v->previous);
		v = v->previous;
	}

	return path;
}

void Graph::computePaths(Vertex* source) {
	resetPathfinding();

	source->minDistance = 0;

	priority_queue<Vertex*> toBeProcessed = priority_queue<Vertex*>();
	toBeProcessed.push(source);

	while(!toBeProcessed.empty()) {
		Vertex* beingProcessed = toBeProcessed.top();
		toBeProcessed.pop();

		for(unsigned int i = 0; i < beingProcessed->adj.size(); i++) {
			Vertex* dest = beingProcessed->adj[i]->destination;
			double distanceToDest = beingProcessed->adj[i]->distance + beingProcessed->minDistance;

			if(distanceToDest < dest->minDistance) {
				dest->minDistance = distanceToDest;
				dest->previous = beingProcessed;

				toBeProcessed.push(dest);
			}
		}
	}
}

Vertex* Graph::getVertexFromID(unsigned int pointID) {
	for (unsigned int i = 0; i < vertexSet.size(); i++) {
		if (vertexSet[i].info.getId() == pointID)
			return &vertexSet[i];
	}

	return NULL;
}

Vertex* Graph::getVertexFromRoadName(const string &roadName) {

	for(unsigned int i = 0; i < vertexSet.size(); i++){
		for(unsigned int j = 0; j < vertexSet[i].getAdj().size();j++){
			if(vertexSet[i].getAdj()[j]->getRoad()->getName().find(roadName) != string::npos){

				return &vertexSet[i];
			}

			if(vertexSet[i].getInfo().getPOI()==roadName)
				return &vertexSet[i];
		}
	}

	return NULL;
}

void Graph::resetVertexes() {
	for(unsigned int i = 0; i < vertexSet.size(); i++) {
		vertexSet[i].visited = false;
	}
}

void Graph::resetPathfinding() {
	for(unsigned int i = 0; i < vertexSet.size(); i++) {
		vertexSet[i].minDistance = DBL_MAX;
		vertexSet[i].previous = NULL;
	}
}

unsigned int Graph::getVertexSetSize() const {
	return vertexSet.size();
}

Vertex* Graph::getVertexFromIndex(unsigned int index) {
	return &vertexSet[index];
}
<|endoftext|>


<commit_before><commit_msg>700k is good<commit_after><|endoftext|>