#ifndef DFGNode_h
#define DFGNode_h
#define DFG_DEBUG_VERBOSE 0
#define DFG_JIT_ASSERT 0
#define DFG_CONSISTENCY_CHECK 0
#define DFG_JIT_BREAK_ON_EVERY_FUNCTION 0
#define DFG_JIT_BREAK_ON_EVERY_BLOCK 0
#define DFG_JIT_BREAK_ON_EVERY_NODE 0
#define DFG_DEBUG_LOCAL_DISBALE 0
#define DFG_DEBUG_LOCAL_DISBALE_SPECULATIVE 0
#define DFG_SUCCESS_STATS 0
#if ENABLE(DFG_JIT)
#include <wtf/Vector.h>
namespace JSC { namespace DFG {
enum VirtualRegister { InvalidVirtualRegister = -1 };
COMPILE_ASSERT(sizeof(VirtualRegister) == sizeof(int), VirtualRegister_is_32bit);
typedef uint32_t NodeIndex;
static const NodeIndex NoNode = UINT_MAX;
typedef uint32_t ExceptionInfo;
#define NodeIdMask 0xFFF
#define NodeResultMask 0xF000
#define NodeMustGenerate 0x10000 // set on nodes that have side effects, and may not trivially be removed by DCE.
#define NodeIsConstant 0x20000
#define NodeIsJump 0x40000
#define NodeIsBranch 0x80000
#define NodeIsTerminal 0x100000
#define NodeResultJS 0x1000
#define NodeResultDouble 0x2000
#define NodeResultInt32 0x3000
#define FOR_EACH_DFG_OP(macro) \
\
macro(JSConstant, NodeResultJS | NodeIsConstant) \
macro(Int32Constant, NodeResultJS | NodeIsConstant) \
macro(DoubleConstant, NodeResultJS | NodeIsConstant) \
macro(ConvertThis, NodeResultJS) \
\
\
macro(GetLocal, NodeResultJS) \
macro(SetLocal, 0) \
macro(Phi, 0) \
\
\
macro(BitAnd, NodeResultInt32) \
macro(BitOr, NodeResultInt32) \
macro(BitXor, NodeResultInt32) \
macro(BitLShift, NodeResultInt32) \
macro(BitRShift, NodeResultInt32) \
macro(BitURShift, NodeResultInt32) \
\
macro(NumberToInt32, NodeResultInt32) \
macro(ValueToInt32, NodeResultInt32 | NodeMustGenerate) \
\
macro(UInt32ToNumber, NodeResultDouble) \
\
\
macro(ArithAdd, NodeResultDouble) \
macro(ArithSub, NodeResultDouble) \
macro(ArithMul, NodeResultDouble) \
macro(ArithDiv, NodeResultDouble) \
macro(ArithMod, NodeResultDouble) \
\
macro(Int32ToNumber, NodeResultDouble) \
macro(ValueToNumber, NodeResultDouble | NodeMustGenerate) \
\
\
macro(ValueAdd, NodeResultJS | NodeMustGenerate) \
\
\
\
\
\
macro(GetByVal, NodeResultJS | NodeMustGenerate) \
macro(PutByVal, NodeMustGenerate) \
macro(PutByValAlias, NodeMustGenerate) \
macro(GetById, NodeResultJS | NodeMustGenerate) \
macro(PutById, NodeMustGenerate) \
macro(PutByIdDirect, NodeMustGenerate) \
macro(GetGlobalVar, NodeResultJS | NodeMustGenerate) \
macro(PutGlobalVar, NodeMustGenerate) \
\
\
macro(CompareLess, NodeResultJS | NodeMustGenerate) \
macro(CompareLessEq, NodeResultJS | NodeMustGenerate) \
macro(CompareEq, NodeResultJS | NodeMustGenerate) \
macro(CompareStrictEq, NodeResultJS) \
\
\
macro(LogicalNot, NodeResultJS) \
\
\
macro(Jump, NodeMustGenerate | NodeIsTerminal | NodeIsJump) \
macro(Branch, NodeMustGenerate | NodeIsTerminal | NodeIsBranch) \
macro(Return, NodeMustGenerate | NodeIsTerminal)
enum NodeId {
#define DFG_OP_ENUM(opcode, flags) opcode##_id,
FOR_EACH_DFG_OP(DFG_OP_ENUM)
#undef DFG_OP_ENUM
};
enum NodeType {
#define DFG_OP_ENUM(opcode, flags) opcode = opcode##_id | (flags),
FOR_EACH_DFG_OP(DFG_OP_ENUM)
#undef DFG_OP_ENUM
};
struct OpInfo {
explicit OpInfo(unsigned value) : m_value(value) {}
unsigned m_value;
};
struct Node {
Node(NodeType op, ExceptionInfo exceptionInfo, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode)
: op(op)
, exceptionInfo(exceptionInfo)
, child1(child1)
, child2(child2)
, child3(child3)
, m_virtualRegister(InvalidVirtualRegister)
, m_refCount(0)
{
}
Node(NodeType op, ExceptionInfo exceptionInfo, OpInfo imm, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode)
: op(op)
, exceptionInfo(exceptionInfo)
, child1(child1)
, child2(child2)
, child3(child3)
, m_virtualRegister(InvalidVirtualRegister)
, m_refCount(0)
, m_opInfo(imm.m_value)
{
}
Node(NodeType op, ExceptionInfo exceptionInfo, OpInfo imm1, OpInfo imm2, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode)
: op(op)
, exceptionInfo(exceptionInfo)
, child1(child1)
, child2(child2)
, child3(child3)
, m_virtualRegister(InvalidVirtualRegister)
, m_refCount(0)
, m_opInfo(imm1.m_value)
{
m_constantValue.opInfo2 = imm2.m_value;
}
bool mustGenerate()
{
return op & NodeMustGenerate;
}
bool isConstant()
{
return op & NodeIsConstant;
}
unsigned constantNumber()
{
ASSERT(isConstant());
return m_opInfo;
}
bool hasLocal()
{
return op == GetLocal || op == SetLocal;
}
VirtualRegister local()
{
ASSERT(hasLocal());
return (VirtualRegister)m_opInfo;
}
bool hasIdentifier()
{
return op == GetById || op == PutById || op == PutByIdDirect;
}
unsigned identifierNumber()
{
ASSERT(hasIdentifier());
return m_opInfo;
}
bool hasVarNumber()
{
return op == GetGlobalVar || op == PutGlobalVar;
}
unsigned varNumber()
{
ASSERT(hasVarNumber());
return m_opInfo;
}
bool hasResult()
{
return op & NodeResultMask;
}
bool hasInt32Result()
{
return (op & NodeResultMask) == NodeResultInt32;
}
bool hasDoubleResult()
{
return (op & NodeResultMask) == NodeResultDouble;
}
bool hasJSResult()
{
return (op & NodeResultMask) == NodeResultJS;
}
bool hasNumericResult()
{
ASSERT((hasInt32Result() || hasDoubleResult()) == !hasJSResult());
return !hasJSResult();
}
int32_t int32Constant()
{
ASSERT(op == Int32Constant);
return m_constantValue.asInt32;
}
void setInt32Constant(int32_t value)
{
ASSERT(op == Int32Constant);
m_constantValue.asInt32 = value;
}
double numericConstant()
{
ASSERT(op == DoubleConstant);
return m_constantValue.asDouble;
}
void setDoubleConstant(double value)
{
ASSERT(op == DoubleConstant);
m_constantValue.asDouble = value;
}
bool isJump()
{
return op & NodeIsJump;
}
bool isBranch()
{
return op & NodeIsBranch;
}
bool isTerminal()
{
return op & NodeIsTerminal;
}
unsigned takenBytecodeOffset()
{
ASSERT(isBranch() || isJump());
return m_opInfo;
}
unsigned notTakenBytecodeOffset()
{
ASSERT(isBranch());
return m_constantValue.opInfo2;
}
VirtualRegister virtualRegister()
{
ASSERT(hasResult());
ASSERT(m_virtualRegister != InvalidVirtualRegister);
return m_virtualRegister;
}
void setVirtualRegister(VirtualRegister virtualRegister)
{
ASSERT(hasResult());
ASSERT(m_virtualRegister == InvalidVirtualRegister);
m_virtualRegister = virtualRegister;
}
bool shouldGenerate()
{
return m_refCount && op != Phi;
}
unsigned refCount()
{
return m_refCount;
}
bool ref()
{
return !m_refCount++;
}
unsigned adjustedRefCount()
{
return mustGenerate() ? m_refCount - 1 : m_refCount;
}
NodeType op;
ExceptionInfo exceptionInfo;
NodeIndex child1, child2, child3;
private:
VirtualRegister m_virtualRegister;
unsigned m_refCount;
unsigned m_opInfo;
union {
int32_t asInt32;
double asDouble;
unsigned opInfo2;
} m_constantValue;
};
} }
#endif
#endif