#pragma once
#include "FunctionExecutable.h"
#include "JSCast.h"
#include "JSFunction.h"
#include "NativeExecutable.h"
namespace JSC {
class CallVariant {
public:
explicit CallVariant(JSCell* callee = nullptr)
: m_callee(callee)
{
}
CallVariant(WTF::HashTableDeletedValueType)
: m_callee(deletedToken())
{
}
explicit operator bool() const { return !!m_callee; }
ALWAYS_INLINE CallVariant despecifiedClosure() const
{
if (m_callee->type() == JSFunctionType)
return CallVariant(jsCast<JSFunction*>(m_callee)->executable());
return *this;
}
JSCell* rawCalleeCell() const { return m_callee; }
InternalFunction* internalFunction() const
{
return jsDynamicCast<InternalFunction*>(*m_callee->vm(), m_callee);
}
JSFunction* function() const
{
return jsDynamicCast<JSFunction*>(*m_callee->vm(), m_callee);
}
bool isClosureCall() const { return !!jsDynamicCast<ExecutableBase*>(*m_callee->vm(), m_callee); }
ExecutableBase* executable() const
{
if (JSFunction* function = this->function())
return function->executable();
return jsDynamicCast<ExecutableBase*>(*m_callee->vm(), m_callee);
}
JSCell* nonExecutableCallee() const
{
RELEASE_ASSERT(!isClosureCall());
return m_callee;
}
Intrinsic intrinsicFor(CodeSpecializationKind kind) const
{
if (ExecutableBase* executable = this->executable())
return executable->intrinsicFor(kind);
return NoIntrinsic;
}
FunctionExecutable* functionExecutable() const
{
if (ExecutableBase* executable = this->executable())
return jsDynamicCast<FunctionExecutable*>(*m_callee->vm(), executable);
return nullptr;
}
NativeExecutable* nativeExecutable() const
{
if (ExecutableBase* executable = this->executable())
return jsDynamicCast<NativeExecutable*>(*m_callee->vm(), executable);
return nullptr;
}
const DOMJIT::Signature* signatureFor(CodeSpecializationKind kind) const
{
if (NativeExecutable* nativeExecutable = this->nativeExecutable())
return nativeExecutable->signatureFor(kind);
return nullptr;
}
bool finalize();
bool merge(const CallVariant&);
void filter(VM&, JSValue);
void dump(PrintStream& out) const;
bool isHashTableDeletedValue() const
{
return m_callee == deletedToken();
}
bool operator==(const CallVariant& other) const
{
return m_callee == other.m_callee;
}
bool operator!=(const CallVariant& other) const
{
return !(*this == other);
}
bool operator<(const CallVariant& other) const
{
return m_callee < other.m_callee;
}
bool operator>(const CallVariant& other) const
{
return other < *this;
}
bool operator<=(const CallVariant& other) const
{
return !(*this < other);
}
bool operator>=(const CallVariant& other) const
{
return other <= *this;
}
unsigned hash() const
{
return WTF::PtrHash<JSCell*>::hash(m_callee);
}
private:
static JSCell* deletedToken() { return bitwise_cast<JSCell*>(static_cast<uintptr_t>(1)); }
JSCell* m_callee;
};
struct CallVariantHash {
static unsigned hash(const CallVariant& key) { return key.hash(); }
static bool equal(const CallVariant& a, const CallVariant& b) { return a == b; }
static const bool safeToCompareToEmptyOrDeleted = true;
};
typedef Vector<CallVariant, 1> CallVariantList;
CallVariantList variantListWithVariant(const CallVariantList&, CallVariant);
CallVariantList despecifiedVariantList(const CallVariantList&);
}
namespace WTF {
template<typename T> struct DefaultHash;
template<> struct DefaultHash<JSC::CallVariant> {
typedef JSC::CallVariantHash Hash;
};
template<typename T> struct HashTraits;
template<> struct HashTraits<JSC::CallVariant> : SimpleClassHashTraits<JSC::CallVariant> { };
}