#ifndef DFGEdge_h
#define DFGEdge_h
#if ENABLE(DFG_JIT)
#include "DFGCommon.h"
#include "DFGUseKind.h"
namespace JSC { namespace DFG {
class AdjacencyList;
class Edge {
public:
explicit Edge(Node* node = 0, UseKind useKind = UntypedUse, ProofStatus proofStatus = NeedsCheck, KillStatus killStatus = DoesNotKill)
#if USE(JSVALUE64)
: m_encodedWord(makeWord(node, useKind, proofStatus, killStatus))
#else
: m_node(node)
, m_encodedWord(makeWord(useKind, proofStatus, killStatus))
#endif
{
}
#if USE(JSVALUE64)
Node* node() const { return bitwise_cast<Node*>(m_encodedWord >> shift()); }
#else
Node* node() const { return m_node; }
#endif
Node& operator*() const { return *node(); }
Node* operator->() const { return node(); }
void setNode(Node* node)
{
#if USE(JSVALUE64)
m_encodedWord = makeWord(node, useKind(), proofStatus(), killStatus());
#else
m_node = node;
#endif
}
UseKind useKindUnchecked() const
{
#if USE(JSVALUE64)
unsigned masked = m_encodedWord & (((1 << shift()) - 1));
unsigned shifted = masked >> 2;
#else
unsigned shifted = static_cast<UseKind>(m_encodedWord) >> 2;
#endif
ASSERT(shifted < static_cast<unsigned>(LastUseKind));
UseKind result = static_cast<UseKind>(shifted);
ASSERT(node() || result == UntypedUse);
return result;
}
UseKind useKind() const
{
ASSERT(node());
return useKindUnchecked();
}
void setUseKind(UseKind useKind)
{
ASSERT(node());
#if USE(JSVALUE64)
m_encodedWord = makeWord(node(), useKind, proofStatus(), killStatus());
#else
m_encodedWord = makeWord(useKind, proofStatus(), killStatus());
#endif
}
ProofStatus proofStatusUnchecked() const
{
return proofStatusForIsProved(m_encodedWord & 1);
}
ProofStatus proofStatus() const
{
ASSERT(node());
return proofStatusUnchecked();
}
void setProofStatus(ProofStatus proofStatus)
{
ASSERT(node());
#if USE(JSVALUE64)
m_encodedWord = makeWord(node(), useKind(), proofStatus, killStatus());
#else
m_encodedWord = makeWord(useKind(), proofStatus, killStatus());
#endif
}
bool isProved() const
{
return proofStatus() == IsProved;
}
bool needsCheck() const
{
return proofStatus() == NeedsCheck;
}
bool willNotHaveCheck() const
{
return isProved() || shouldNotHaveTypeCheck(useKind());
}
bool willHaveCheck() const
{
return !willNotHaveCheck();
}
KillStatus killStatusUnchecked() const
{
return killStatusForDoesKill(m_encodedWord & 2);
}
KillStatus killStatus() const
{
ASSERT(node());
return killStatusUnchecked();
}
void setKillStatus(KillStatus killStatus)
{
ASSERT(node());
#if USE(JSVALUE64)
m_encodedWord = makeWord(node(), useKind(), proofStatus(), killStatus);
#else
m_encodedWord = makeWord(useKind(), proofStatus(), killStatus);
#endif
}
bool doesKill() const { return DFG::doesKill(killStatus()); }
bool doesNotKill() const { return !doesKill(); }
bool isSet() const { return !!node(); }
Edge sanitized() const
{
Edge result = *this;
#if USE(JSVALUE64)
result.m_encodedWord = makeWord(node(), useKindUnchecked(), NeedsCheck, DoesNotKill);
#else
result.m_encodedWord = makeWord(useKindUnchecked(), NeedsCheck, DoesNotKill);
#endif
return result;
}
typedef void* Edge::*UnspecifiedBoolType;
operator UnspecifiedBoolType*() const { return reinterpret_cast<UnspecifiedBoolType*>(isSet()); }
bool operator!() const { return !isSet(); }
bool operator==(Edge other) const
{
#if USE(JSVALUE64)
return m_encodedWord == other.m_encodedWord;
#else
return m_node == other.m_node && m_encodedWord == other.m_encodedWord;
#endif
}
bool operator!=(Edge other) const
{
return !(*this == other);
}
void dump(PrintStream&) const;
unsigned hash() const
{
#if USE(JSVALUE64)
return IntHash<uintptr_t>::hash(m_encodedWord);
#else
return PtrHash<Node*>::hash(m_node) + m_encodedWord;
#endif
}
private:
friend class AdjacencyList;
#if USE(JSVALUE64)
static uint32_t shift() { return 7; }
static uintptr_t makeWord(Node* node, UseKind useKind, ProofStatus proofStatus, KillStatus killStatus)
{
ASSERT(sizeof(node) == 8);
uintptr_t shiftedValue = bitwise_cast<uintptr_t>(node) << shift();
ASSERT((shiftedValue >> shift()) == bitwise_cast<uintptr_t>(node));
ASSERT(useKind >= 0 && useKind < LastUseKind);
ASSERT((static_cast<uintptr_t>(LastUseKind) << 2) <= (static_cast<uintptr_t>(2) << shift()));
return shiftedValue | (static_cast<uintptr_t>(useKind) << 2) | (DFG::doesKill(killStatus) << 1) | DFG::isProved(proofStatus);
}
#else
static uintptr_t makeWord(UseKind useKind, ProofStatus proofStatus, KillStatus killStatus)
{
return (static_cast<uintptr_t>(useKind) << 2) | (DFG::doesKill(killStatus) << 1) | DFG::isProved(proofStatus);
}
Node* m_node;
#endif
uintptr_t m_encodedWord;
};
inline bool operator==(Edge edge, Node* node)
{
return edge.node() == node;
}
inline bool operator==(Node* node, Edge edge)
{
return edge.node() == node;
}
inline bool operator!=(Edge edge, Node* node)
{
return edge.node() != node;
}
inline bool operator!=(Node* node, Edge edge)
{
return edge.node() != node;
}
} }
#endif // ENABLE(DFG_JIT)
#endif // DFGEdge_h