#pragma once
#if ENABLE(B3_JIT)
#include "AirKind.h"
#include "B3StackmapSpecial.h"
#include <wtf/HashMap.h>
namespace JSC { namespace B3 {
namespace Air {
struct Inst;
}
class CheckSpecial final : public StackmapSpecial {
public:
class Key {
public:
Key()
: m_stackmapRole(SameAsRep)
, m_numArgs(0)
{
}
Key(Air::Kind kind, unsigned numArgs, RoleMode stackmapRole = SameAsRep)
: m_kind(kind)
, m_stackmapRole(stackmapRole)
, m_numArgs(numArgs)
{
}
explicit Key(const Air::Inst&);
bool operator==(const Key& other) const
{
return m_kind == other.m_kind
&& m_numArgs == other.m_numArgs
&& m_stackmapRole == other.m_stackmapRole;
}
bool operator!=(const Key& other) const
{
return !(*this == other);
}
explicit operator bool() const { return *this != Key(); }
Air::Kind kind() const { return m_kind; }
unsigned numArgs() const { return m_numArgs; }
RoleMode stackmapRole() const { return m_stackmapRole; }
void dump(PrintStream& out) const;
Key(WTF::HashTableDeletedValueType)
: m_stackmapRole(SameAsRep)
, m_numArgs(1)
{
}
bool isHashTableDeletedValue() const
{
return *this == Key(WTF::HashTableDeletedValue);
}
unsigned hash() const
{
return m_kind.hash() + m_numArgs + m_stackmapRole;
}
private:
Air::Kind m_kind;
RoleMode m_stackmapRole;
unsigned m_numArgs;
};
CheckSpecial(Air::Kind, unsigned numArgs, RoleMode stackmapRole = SameAsRep);
CheckSpecial(const Key&);
~CheckSpecial() final;
private:
Air::Inst hiddenBranch(const Air::Inst&) const;
void forEachArg(Air::Inst&, const ScopedLambda<Air::Inst::EachArgCallback>&) final;
bool isValid(Air::Inst&) final;
bool admitsStack(Air::Inst&, unsigned argIndex) final;
bool admitsExtendedOffsetAddr(Air::Inst&, unsigned) final;
Optional<unsigned> shouldTryAliasingDef(Air::Inst&) final;
MacroAssembler::Jump generate(Air::Inst&, CCallHelpers&, Air::GenerationContext&) final;
void dumpImpl(PrintStream&) const final;
void deepDumpImpl(PrintStream&) const final;
Air::Kind m_checkKind;
RoleMode m_stackmapRole;
unsigned m_numCheckArgs;
};
struct CheckSpecialKeyHash {
static unsigned hash(const CheckSpecial::Key& key) { return key.hash(); }
static bool equal(const CheckSpecial::Key& a, const CheckSpecial::Key& b) { return a == b; }
static constexpr bool safeToCompareToEmptyOrDeleted = true;
};
} }
namespace WTF {
template<typename T> struct DefaultHash;
template<> struct DefaultHash<JSC::B3::CheckSpecial::Key> : JSC::B3::CheckSpecialKeyHash { };
template<typename T> struct HashTraits;
template<> struct HashTraits<JSC::B3::CheckSpecial::Key> : SimpleClassHashTraits<JSC::B3::CheckSpecial::Key> {
static constexpr bool emptyValueIsZero = false;
};
}
#endif // ENABLE(B3_JIT)