#pragma once
#if ENABLE(B3_JIT)
#include "B3HeapRange.h"
#include "B3Kind.h"
#include "B3Origin.h"
#include "B3Type.h"
#include <wtf/HashTable.h>
namespace JSC { namespace B3 {
class Procedure;
class Value;
class ValueKey {
public:
ValueKey()
{
}
ValueKey(Kind kind, Type type)
: m_kind(kind)
, m_type(type)
{
}
ValueKey(Kind, Type, Value* child);
ValueKey(Kind, Type, Value* left, Value* right);
ValueKey(Kind, Type, Value* a, Value* b, Value* c);
ValueKey(Kind kind, Type type, int64_t value)
: m_kind(kind)
, m_type(type)
{
u.value = value;
}
ValueKey(Kind kind, Type type, double value)
: m_kind(kind)
, m_type(type)
{
u.doubleValue = value;
}
ValueKey(Kind kind, Type type, float value)
: m_kind(kind)
, m_type(type)
{
u.floatValue = value;
}
static ValueKey intConstant(Type type, int64_t value);
Kind kind() const { return m_kind; }
Opcode opcode() const { return kind().opcode(); }
Type type() const { return m_type; }
unsigned childIndex(unsigned index) const { return u.indices[index]; }
Value* child(Procedure&, unsigned index) const;
int64_t value() const { return u.value; }
double doubleValue() const { return u.doubleValue; }
double floatValue() const { return u.floatValue; }
bool operator==(const ValueKey& other) const
{
return m_kind == other.m_kind
&& m_type == other.m_type
&& u == other.u;
}
bool operator!=(const ValueKey& other) const
{
return !(*this == other);
}
unsigned hash() const
{
return m_kind.hash() + m_type + WTF::IntHash<int32_t>::hash(u.indices[0]) + u.indices[1] + u.indices[2];
}
explicit operator bool() const { return *this != ValueKey(); }
void dump(PrintStream&) const;
bool canMaterialize() const
{
if (!*this)
return false;
switch (opcode()) {
case CheckAdd:
case CheckSub:
case CheckMul:
return false;
default:
return true;
}
}
bool isConstant() const
{
return B3::isConstant(opcode());
}
Value* materialize(Procedure&, Origin) const;
ValueKey(WTF::HashTableDeletedValueType)
: m_type { Int32 }
{
}
bool isHashTableDeletedValue() const
{
return *this == ValueKey(WTF::HashTableDeletedValue);
}
private:
Kind m_kind;
Type m_type { Void };
union U {
unsigned indices[3];
int64_t value;
double doubleValue;
float floatValue;
U()
{
indices[0] = 0;
indices[1] = 0;
indices[2] = 0;
}
bool operator==(const U& other) const
{
return indices[0] == other.indices[0]
&& indices[1] == other.indices[1]
&& indices[2] == other.indices[2];
}
} u;
};
struct ValueKeyHash {
static unsigned hash(const ValueKey& key) { return key.hash(); }
static bool equal(const ValueKey& a, const ValueKey& b) { return a == b; }
static const bool safeToCompareToEmptyOrDeleted = true;
};
} }
namespace WTF {
template<typename T> struct DefaultHash;
template<> struct DefaultHash<JSC::B3::ValueKey> {
typedef JSC::B3::ValueKeyHash Hash;
};
template<typename T> struct HashTraits;
template<> struct HashTraits<JSC::B3::ValueKey> : public SimpleClassHashTraits<JSC::B3::ValueKey> {
static const bool emptyValueIsZero = false;
};
}
#endif // ENABLE(B3_JIT)