#pragma once
#if ENABLE(WEBASSEMBLY)
#include "B3Type.h"
#include "WasmOps.h"
#include <cstdint>
#include <cstring>
#include <wtf/CheckedArithmetic.h>
#include <wtf/HashMap.h>
#include <wtf/HashTraits.h>
#include <wtf/StdLibExtras.h>
#include <wtf/ThreadSafeRefCounted.h>
#include <wtf/Vector.h>
namespace WTF {
class PrintStream;
}
namespace JSC {
namespace Wasm {
using SignatureArgCount = uint32_t;
using SignatureIndex = uint32_t;
class Signature : public ThreadSafeRefCounted<Signature> {
WTF_MAKE_FAST_ALLOCATED;
static const constexpr SignatureArgCount s_retCount = 1;
Signature() = delete;
Signature(const Signature&) = delete;
Signature(SignatureArgCount argCount)
: m_argCount(argCount)
{
}
Type* storage(SignatureArgCount i)
{
return i + reinterpret_cast<Type*>(reinterpret_cast<char*>(this) + sizeof(Signature));
}
Type* storage(SignatureArgCount i) const { return const_cast<Signature*>(this)->storage(i); }
static size_t allocatedSize(Checked<SignatureArgCount> argCount)
{
return (sizeof(Signature) + (s_retCount + argCount) * sizeof(Type)).unsafeGet();
}
public:
Type& returnType() { return *storage(0); }
Type returnType() const { return *storage(0); }
SignatureArgCount returnCount() const { return s_retCount; }
SignatureArgCount argumentCount() const { return m_argCount; }
Type& argument(SignatureArgCount i)
{
ASSERT(i < argumentCount());
return *storage(returnCount() + i);
}
Type argument(SignatureArgCount i) const { return const_cast<Signature*>(this)->argument(i); }
WTF::String toString() const;
void dump(WTF::PrintStream& out) const;
bool operator==(const Signature& rhs) const
{
if (argumentCount() != rhs.argumentCount())
return false;
if (returnType() != rhs.returnType())
return false;
for (unsigned i = 0; i < argumentCount(); ++i) {
if (argument(i) != rhs.argument(i))
return false;
}
return true;
}
unsigned hash() const;
static RefPtr<Signature> tryCreate(SignatureArgCount);
static const constexpr SignatureIndex invalidIndex = 0;
static const constexpr SignatureIndex firstValidIndex = invalidIndex + 1;
private:
friend class SignatureInformation;
SignatureArgCount m_argCount;
};
struct SignatureHash {
const Signature* key;
static const Signature* empty() { return nullptr; }
static const Signature* deleted() { return reinterpret_cast<const Signature*>(1); }
SignatureHash()
: key(empty())
{
}
explicit SignatureHash(const Signature* key)
: key(key)
{
ASSERT(key != empty());
ASSERT(key != deleted());
}
explicit SignatureHash(WTF::HashTableDeletedValueType)
: key(deleted())
{
}
bool operator==(const SignatureHash& rhs) const { return equal(*this, rhs); }
static bool equal(const SignatureHash& lhs, const SignatureHash& rhs) { return lhs.key == rhs.key || (lhs.key && rhs.key && *lhs.key == *rhs.key); }
static unsigned hash(const SignatureHash& signature) { return signature.key->hash(); }
static const bool safeToCompareToEmptyOrDeleted = false;
bool isHashTableDeletedValue() const { return key == deleted(); }
};
} }
namespace WTF {
template<typename T> struct DefaultHash;
template<> struct DefaultHash<JSC::Wasm::SignatureHash> {
typedef JSC::Wasm::SignatureHash Hash;
};
template<typename T> struct HashTraits;
template<> struct HashTraits<JSC::Wasm::SignatureHash> : SimpleClassHashTraits<JSC::Wasm::SignatureHash> {
static const bool emptyValueIsZero = true;
};
}
namespace JSC { namespace Wasm {
class SignatureInformation {
WTF_MAKE_NONCOPYABLE(SignatureInformation);
SignatureInformation();
public:
static SignatureInformation& singleton();
static std::pair<SignatureIndex, Ref<Signature>> WARN_UNUSED_RETURN adopt(Ref<Signature>&&);
static const Signature& WARN_UNUSED_RETURN get(SignatureIndex);
static SignatureIndex WARN_UNUSED_RETURN get(const Signature&);
static void tryCleanup();
private:
HashMap<Wasm::SignatureHash, Wasm::SignatureIndex> m_signatureMap;
HashMap<Wasm::SignatureIndex, Ref<Signature>> m_indexMap;
SignatureIndex m_nextIndex { Signature::firstValidIndex };
Lock m_lock;
};
} }
#endif // ENABLE(WEBASSEMBLY)